{"id":339283,"date":"2022-10-04T09:00:32","date_gmt":"2022-10-04T09:00:32","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=339283"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=339283","title":{"rendered":"<span>Kotlin. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0427\u0430\u0441\u0442\u044c 3). \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f Kotest \u0438 Spring Test<\/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-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/4u\/ri\/zl\/4urizlf0negicujw9_d9qhoafia.jpeg\" alt=\"Kotest\" data-src=\"https:\/\/habrastorage.org\/webt\/4u\/ri\/zl\/4urizlf0negicujw9_d9qhoafia.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u043d\u0430 <strong>Kotlin<\/strong> \u0438 \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 <strong>Kotest<\/strong><\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f <code>Kotest<\/code>:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0427\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435<\/li>\n<li>\u041a\u0430\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b<\/li>\n<li>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0432 <code>Kotest<\/code> <\/li>\n<li>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f<\/li>\n<li>\u041f\u0440\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f <strong>Spring<\/strong><\/li>\n<li>\u0423\u0433\u043b\u0443\u0431\u043b\u044e\u0441\u044c \u0432 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e <strong>Kotest<\/strong> \u0438 <strong>Spring Boot Test<\/strong><\/li>\n<li>\u0421\u0440\u0430\u0432\u043d\u044e \u0441 <strong>Junit5<\/strong><\/li>\n<li>\u0418 \u043d\u0430 \u0437\u0430\u043a\u0443\u0441\u043a\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u044e \u043e\u0442\u0447\u0435\u0442\u044b <strong>Allure<\/strong><\/li>\n<\/ul>\n<p>  <\/p>\n<blockquote><p>\u26a0\ufe0f\u0411\u0443\u0434\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432.<\/p><\/blockquote>\n<p>\u0412\u0441\u0435 \u0447\u0430\u0441\u0442\u0438 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0430:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/520380\/\">Kotlin. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0447\u0430\u0441\u0442\u044c 1). Kotest: \u041d\u0430\u0447\u0430\u043b\u043e<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/company\/nspk\/blog\/542754\/\">Kotlin. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0427\u0430\u0441\u0442\u044c 2). Kotest. Deep Diving<\/a><a name=\"habracut\"><\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"o-sebe\">\u041e \u0441\u0435\u0431\u0435<\/h2>\n<p>  <\/p>\n<p>\u041c\u0430\u043a\u0441\u0438\u043c \u041a\u043e\u0447\u0435\u0442\u043a\u043e\u0432, <strong>QA \u041b\u0438\u0434 \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438<\/strong> \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 <a href=\"https:\/\/habr.com\/ru\/company\/nspk\/\">\u041c\u0438\u0440 Plat.Form (\u041d\u0421\u041f\u041a)<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 <a href=\"https:\/\/transport.nspk.ru\/portal\/home\">\u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433\u043e\u0432\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b<\/a> \u0437\u0430\u0440\u043e\u0434\u0438\u043b\u0441\u044f 3 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u0438 \u0432\u044b\u0440\u043e\u0441 \u0434\u043e \u0447\u0435\u0442\u044b\u0440\u0435\u0445 \u043a\u043e\u043c\u0430\u043d\u0434, \u0433\u0434\u0435 \u0442\u0440\u0443\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0431\u0449\u0435\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0431\u043e\u043b\u0435\u0435 <strong>10 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0432 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 (SDET)<\/strong>, \u0430 \u0435\u0449\u0435 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u2014 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0439 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u0438 <strong>E2E<\/strong> \u0434\u043e \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0432 <strong>\u0440\u0435\u043b\u0438\u0437<\/strong> \u2014 \u0432\u0441\u0435\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430 40 \u043c\u0438\u043a\u0440\u043e-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u041e\u0442 1 \u0434\u043e 5 \u043c\u0438\u043a\u0440\u043e-\u0440\u0435\u043b\u0438\u0437\u043e\u0432 \u0432 \u043d\u0435\u0434\u0435\u043b\u044e.<\/p>\n<p>  <\/p>\n<p>\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438 \u2014 <code>Kafka<\/code>, \u0432\u043d\u0435\u0448\u043d\u0438\u0439 API \u2014 REST, \u0430 \u0442\u0430\u043a\u0436\u0435 3 \u0444\u0440\u043e\u043d\u0442\u043e\u0432\u044b\u0445 Web \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0430\u043c\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432\u0435\u0434\u0435\u0442\u0441\u044f \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 <strong>Kotlin<\/strong>, \u0430 \u0434\u0432\u0438\u0436\u043e\u043a \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u044b\u043b \u0432\u044b\u0431\u0440\u0430\u043d <strong>Kotest<\/strong>.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0438 \u0432 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f\u0445 \u0441\u0435\u0440\u0438\u0438 \u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u044e \u043e \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u0414\u0432\u0438\u0436\u043a\u0435 \u0438 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u0445 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <strong>\u0420\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0430\/Tutorial<\/strong>.<\/p>\n<p>  <\/p>\n<h2 id=\"paradigma-rasshireniy\">\u041f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439<\/h2>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f?<\/p>\n<p>  <\/p>\n<p><strong>\u042d\u0442\u043e \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441-\u043c\u0430\u0440\u043a\u0435\u0440 \u0434\u043b\u044f \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u0435\u0433\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b.<\/strong><\/p>\n<p>  <\/p>\n<p><strong>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u043e \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430.<\/strong><\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0442\u0435\u0441\u0442, \u0442\u043e \u0435\u0441\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b.<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">interface EnabledExtension : Extension {      suspend fun isEnabled(descriptor: Descriptor): Enabled }<\/code><\/pre>\n<p>  <\/p>\n<p><strong>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \/ \u043a\u043b\u0430\u0441\u0441\u0443 \/ \u0442\u0435\u0441\u0442\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0438\u043b\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e: \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0432 \u0440\u0435\u0435\u0441\u0442\u0440 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439.<\/strong><\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f Junit5 \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043a\u043b\u0430\u0441\u0441 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>@ExtendWith<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">@ExtendWith(SpringExtension::class) internal class Junit5Test <\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u044d\u0442\u043e\u0439 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043c\u0435\u0442\u0438\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"java\">@ExtendWith(SpringExtension.class) public @interface SpringBootTest { }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u2014 \u044d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u043b\u044f \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430.<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0412 Junit4 \u2014 \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b <code>TestRule<\/code> \u0438 <code>MethodRule<\/code><\/li>\n<li>\u0412 Junit5 \u2014 \u044d\u0442\u043e <code>Extension<\/code><\/li>\n<li>\u0412 Kotest \u2014 \u0442\u043e\u0436\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>Extension<\/code><\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u042f \u0431\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u043b \u0434\u0432\u0430 \u0432\u0438\u0434\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0432 <code>Kotest<\/code>: <code>Listener<\/code> \u0438 <code>Interceptor<\/code><\/p>\n<p>  <\/p>\n<h3 id=\"listener\">Listener<\/h3>\n<p>  <\/p>\n<ul>\n<li>\u041d\u0430 \u0432\u0445\u043e\u0434 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>TestCase<\/code> \u0438\u043b\u0438 <code>TestResult<\/code>, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0435\u0449\u0435 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442;<\/li>\n<li>\u0427\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0442\u0440\u0430\u043d\u0441\u043b\u0438\u0440\u0443\u0435\u0442 \u0432 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0435\u043f\u043e\u0440\u0442\u0435;<\/li>\n<li>\u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442, \u043b\u0438\u0431\u043e \u043e\u0442\u0434\u0430\u0435\u0442 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u043b\u044f \u0436\u0443\u0440\u043d\u0430\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0438\u0439\u0441\u044f \u0432 <code>Kotest<\/code> \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>InstantiationErrorListener<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u0442\u0435\u0441\u0442\u0430. \u041e\u043d \u0440\u0435\u0448\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u043a\u043e\u0433\u0434\u0430 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043d\u0435\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0438\u043b\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043b\u0430\u0441\u0441 \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c. \u0422\u043e\u0433\u0434\u0430 \u0432 \u043e\u0442\u0447\u0435\u0442\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043d\u0435\u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u0441\u0442, \u043e\u0442\u0447\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u043c, \u0430 \u0441\u0431\u043e\u0440\u043a\u0430 \u043f\u0440\u043e\u0432\u0430\u043b\u0435\u043d\u043d\u043e\u0439.<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">interface InstantiationErrorListener : Extension {     suspend fun instantiationError(kclass: KClass&lt;*>, t: Throwable) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u0441\u0435 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u0432\u043b\u0438\u044f\u044e\u0442 \u043d\u0430 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0442\u0435\u0441\u0442\u0430 \u0438 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0430, \u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0439 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e.<\/p>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0432\u043e\u0435 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043f\u0435\u0440\u0435\u0434 \u043d\u0430\u0447\u0430\u043b\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044f\u0445<br \/>  <code>BeforeInvocationListener<\/code>:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/_z\/ze\/fv\/_zzefvos7v0i4lqcq0qrxvwy_7s.png\" data-src=\"https:\/\/habrastorage.org\/webt\/_z\/ze\/fv\/_zzefvos7v0i4lqcq0qrxvwy_7s.png\"\/><\/p>\n<p>  <\/p>\n<h3 id=\"interceptor\">Interceptor<\/h3>\n<p>  <\/p>\n<ul>\n<li>\u041d\u0430 \u0432\u0445\u043e\u0434 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e;<\/li>\n<li>\u0427\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0430 \u043c\u043e\u0436\u0435\u0442 \u0438 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044e;<\/li>\n<li>\u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u043e\u0432\u0443\u044e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u0438\u043b\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0439;<\/li>\n<li>\u0412\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u043b\u0438\u044f\u044e\u0442 \u043d\u0430 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u0442\u0435\u0441\u0442\u0430;<\/li>\n<li>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 ((\u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430) \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a\u0443 \u0438\u043b\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044e \u043a\u0430\u043a \u0432 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0435 <code>Chain of Responsibility<\/code>.<\/li>\n<\/ul>\n<p>  <\/p>\n<blockquote><p>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 <code>Interceptor<\/code> \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u2014 \u043d\u0435 \u0444\u0430\u043a\u0442, \u0447\u0442\u043e \u043e\u043d\u043e \u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0435\u0442 \u0432 \u0438\u043c\u0435\u043d\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0434 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/p><\/blockquote>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435: <code>ConstructorExtension<\/code>.<br \/>  \u041e\u043d\u043e \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 \u0442\u0435\u0441\u0442\u0430, \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u2014 <code>Spec<\/code>. <\/p>\n<p>  <\/p>\n<p>\u0422\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u043a\u0430\u043a \u0432 <code>InstantiationErrorListener<\/code>, \u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0432\u0437\u044f\u0442\u044c \u043d\u0430 \u0441\u0435\u0431\u044f \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0437\u0430 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0443 \u0432\u0441\u0435\u0433\u043e \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0435.<\/p>\n<p>  <\/p>\n<blockquote><p>\u0421\u0440\u0430\u0437\u0443 \u043e\u0442\u0432\u0435\u0447\u0430\u044e \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441: <code>\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0435\u0441\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u043a\u0438\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439?<\/code><br \/>  \u0411\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0432 \u0440\u0435\u0435\u0441\u0442\u0440, \u0435\u0441\u043b\u0438 \u043e\u043d\u043e \u0432\u0435\u0440\u043d\u0435\u0442 \u043d\u0435 <code>null<\/code>. \u041b\u0438\u0431\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f <code>Spec<\/code> \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<\/p><\/blockquote>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 <code>Kotest<\/code> \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u043c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a\u0430\u043c \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0438\u0441\u043a \u0438 \u0437\u0430\u043f\u0443\u0441\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/tt\/pv\/dk\/ttpvdksb5cpvg7pbdqer7knuj2e.png\" data-src=\"https:\/\/habrastorage.org\/webt\/tt\/pv\/dk\/ttpvdksb5cpvg7pbdqer7knuj2e.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0412 \u0445\u043e\u0434\u0435 \u044d\u0442\u043e\u0433\u043e \u044d\u0442\u0430\u043f\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f <a href=\"https:\/\/en.wikipedia.org\/wiki\/Fold_(higher-order_function)\">\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0441\u0448\u0435\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f fold<\/a>, \u0441 \u043f\u043e\u0440\u044f\u0434\u043a\u043e\u043c, \u0440\u0430\u0432\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a\u043e\u0432. \u0422\u043e \u0435\u0441\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a\u0430, \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u0432\u044b\u0448\u0435\u0441\u0442\u043e\u044f\u0449\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e.<\/p>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a \u2014 \u0432 \u044f\u0434\u0440\u0435 Kotest <code>5.4.1<\/code> \u044d\u0442\u043e <code>TestPathContextInterceptor<\/code>, \u043e\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0443 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 <code>coroutine<\/code> \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a.<\/li>\n<li><code>2<\/code> \u0413\u0434\u0435-\u0442\u043e \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f <code>TestCaseExtensionInterceptor<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u0438\u0449\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a\u0438 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0443\u0436\u0435 \u0438\u0445.<\/li>\n<li><code>3<\/code> \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0434\u0432\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a\u0430: <code>KotestAllureListener<\/code> \u0438 <code>SpringTestExtension<\/code><\/li>\n<li><code>4<\/code> \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f <code>CoroutineDebugProbeInterceptor<\/code> \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0441\u0432\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u0432\u044b\u0437\u0432\u0430\u0432\u0448\u0438\u0439 \u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0434\u043e \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430<\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"kak-rasshireniya-pomogayut-pisat-testy\">\u041a\u0430\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b?<\/h2>\n<p>  <\/p>\n<p>\u0422\u043e\u0442 \u0436\u0435 <code>Spring Test<\/code> \u043c\u043e\u0436\u043d\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u043e \u0441 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c \u0424\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043a \u043d\u0438\u043c.<\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430 \u0435\u0434\u0438\u043d\u043e\u0439 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u043e\u0432-\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432, \u0430 \u0432\u0441\u0435 \u0432\u044b\u0437\u043e\u0432\u044b \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0434\u0438\u043d\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0435.<\/p>\n<p>  <\/p>\n<p>\u041e\u0447\u0435\u043d\u044c \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0443\u0431\u043b\u0451\u0440\u043e\u0432 (test doubles).<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f <code>MockitoExtension<\/code> \u0434\u043b\u044f <code>Junit5<\/code> \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0438 \u0432\u0441\u0435\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432 \u0438 \u043d\u0435 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u044c\u043d\u0443\u044e \u0431\u0430\u0437\u0443, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@Mock<\/code> \u043d\u0430 \u043f\u043e\u043b\u0435.<\/p>\n<p>  <\/p>\n<blockquote><p>\u041e\u043f\u0443\u0441\u043a\u0430\u044f \u043c\u043e\u043c\u0435\u043d\u0442 \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 &#8230;<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"kotlin\">@ExtendWith(MockitoExtension::class) internal class Junit5Test {      @Mock UserRepository userRepository }<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0431\u0435\u0440\u0435\u0442 \u043d\u0430 \u0441\u0435\u0431\u044f \u0432\u0441\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f;<\/li>\n<li>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u0442 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0438 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u043a \u0446\u0438\u043a\u043b\u0443 \u0442\u0435\u0441\u0442\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u044e \u043c\u0435\u0436\u0434\u0443 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c\u0438;<\/li>\n<li>\u041e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0435\u0442 \u0440\u0435\u0441\u0443\u0440\u0441\u044b;<\/li>\n<li>\u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0438;<\/li>\n<li>\u0418 \u043c\u043d\u043e\u0433\u043e \u0447\u0435\u0433\u043e \u0435\u0449\u0435, \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f.<\/li>\n<\/ul>\n<p>  <\/p>\n<blockquote><p>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u043a\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432.<br \/>  \u0410 \u0442\u0430\u043a\u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u0442\u0435\u0441\u0442\u0430\u0445, \u0442\u0430\u043a \u043a\u0430\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0441\u0430\u043c\u0438 \u043e\u0442\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b, \u0430 \u0432\u0430\u0448 \u043a\u043e\u0434 \u043e\u0431\u0432\u044f\u0437\u043a\u0438 \u0442\u0435\u0441\u0442\u043e\u0432 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043d\u0435\u0442.<\/p><\/blockquote>\n<p>  <\/p>\n<h2 id=\"nemnogo-vstroennyh-rasshireniy-kotest\">\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 Kotest<\/h2>\n<p>  <\/p>\n<p>\u0412\u0441\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c \u0435\u0441\u0442\u044c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <a href=\"https:\/\/kotest.io\/docs\/extensions\/extensions.html\">Extensions<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u043c\u044b \u0437\u0434\u0435\u0441\u044c \u0441\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435, \u0430 \u043d\u0435 \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e.<\/p>\n<p>  <\/p>\n<blockquote><p>\u041e\u0434\u043d\u0430\u043a\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0443 \u043d\u0438\u0445 \u0441\u0443\u043f\u0435\u0440 \u043a\u043b\u0430\u0441\u0441\u043d\u0430\u044f! \u0415\u0441\u0442\u044c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0435!  <\/p>\n<ul>\n<li>\u0412\u0435\u0440\u0441\u0438\u0438 \u043f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0435\u043b\u0438\u0437;<\/li>\n<li>\u0423\u0434\u043e\u0431\u043d\u0430\u044f \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f;<\/li>\n<li>\u041f\u0440\u0438\u044f\u0442\u043d\u044b\u0439 \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0438\u0437\u0430\u0439\u043d;<\/li>\n<li>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 <code>Changelog<\/code>;<\/li>\n<li>\u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0441\u0442\u0430\u0442\u044c\u0438 \/ <code>StackOverflow<\/code> \/ <code>GitHub<\/code> \/ \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0438 snapshot \u0432\u0435\u0440\u0441\u0438\u0438.<\/li>\n<\/ul>\n<p>  \u0412\u0441\u0435 \u044d\u0442\u043e \u0437\u0430\u0441\u043b\u0443\u0433\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 <code>Kotest<\/code> \u0438 \u0424\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 <code>Docusaurus 2.0<\/code> \u2014 \u043c\u043e\u0439 \u043b\u0430\u0439\u043a <a href=\"https:\/\/github.com\/facebook\/docusaurus\">Docusaurus 2.0<\/a><\/p><\/blockquote>\n<p>\u0412 <code>Kotest<\/code> \u0435\u0441\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439. \u0412\u0441\u0435 \u043e\u043d\u0438 \u0432 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0435 <code>io.kotest:kotest-extensions-jvm<\/code>,<br \/>  \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0430\u043d\u0437\u0438\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c <code>io.kotest:kotest-runner-junit5<\/code>.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043f\u0430\u043a\u0435\u0442\u0435 <code>io.kotest.extensions<\/code> \u2014 \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u043c\u0435\u0439\u0442\u0435 \u044d\u0442\u043e \u0432\u0432\u0438\u0434\u0443, \u0442\u0430\u043c \u0438\u0445 \u043c\u043d\u043e\u0433\u043e, \u0430 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e.<\/p>\n<p>  <\/p>\n<h4 id=\"vozmem-rasshirenie-systemenvironmenttestlistener\">\u0412\u043e\u0437\u044c\u043c\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 <code>SystemEnvironmentTestListener<\/code><\/h4>\n<p>  <\/p>\n<p>\u0412\u0441\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u2014 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 <code>SystemEnvironmentTestListener<\/code> \u043c\u044b \u0437\u0430\u0434\u0430\u0435\u043c \u043d\u0430\u0431\u043e\u0440 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u043c\u0435\u043d\u044f\u0435\u043c \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0435\u0441\u0442\u0430.<\/p>\n<p>  <\/p>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u0441\u0442\u0430 \u044d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c. \u041f\u043e\u0441\u043b\u0435 \u0442\u0435\u0441\u0442\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0441\u0432\u043e\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043d\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043c\u0435\u0447\u0430\u0442\u044c \u0442\u0435\u0441\u0442 <code>@DoNotParallelize<\/code> \u2014 \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043d\u0435 \u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u0442\u0435\u0441\u0442\u044b \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e, \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043c\u0435\u0442\u0438\u0442\u044c!<\/p>\n<p>  <\/p>\n<p>\u041b\u0438\u0431\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0441\u0440\u0430\u0437\u0443 \u043a\u043e \u0432\u0441\u0435\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443.<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">@DoNotParallelize internal class KotestSystemEnvironmentTest : StringSpec() {      \/* 1 *\/     override fun extensions() =         listOf(SystemEnvironmentTestListener(\/* 2 *\/mapOf(\"USERNAME\" to \"TEST\", \"OS\" to \"Astra Linux\"), \/* 3 *\/OverrideMode.SetOrOverride))      init {         \/* 4 *\/         println(\"Before use listener: \" + System.getenv(\"USERNAME\"))         println(\"Before use listener: \" + System.getenv(\"OS\"))          \"Scenario: environment variables should be mocked\" {             \/* 5 *\/             System.getenv(\"USERNAME\") shouldBe \"TEST\"             System.getenv(\"OS\") shouldBe \"Astra Linux\"         }     } }<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/li>\n<li><code>2<\/code> \u0421\u043b\u043e\u0432\u0430\u0440\u044c \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0438 \u043d\u043e\u0432\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438.<\/li>\n<li><code>3<\/code> \u0420\u0435\u0436\u0438\u043c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f. \u0414\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e. \u0410 <code>OverrideMode.SetOrError<\/code>, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442, \u043d\u043e \u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439 \u0435\u0441\u043b\u0438 \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e.<\/li>\n<li><code>4<\/code> \u0412 \u044d\u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0432\u044b\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0432\u0441\u0435 \u0435\u0449\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/li>\n<li><code>5<\/code> \u0410 \u0432 \u0442\u0435\u0441\u0442\u0435 \u0443\u0436\u0435 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435.<\/li>\n<\/ul>\n<p>  <\/p>\n<blockquote><p>\u041a\u0441\u0442\u0430\u0442\u0438 \u043a\u043b\u0430\u0441\u0441 <code>OverrideMode<\/code> \u2014 \u044d\u0442\u043e <code>sealed class<\/code><br \/>  \u0418 \u0432 <code>Kotest<\/code> \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u043c\u0435\u0441\u0442\u043e <code>enum<\/code>-\u043e\u0432 <code>sealed class<\/code>-\u043e\u0432<\/p><\/blockquote>\n<p>  <\/p>\n<h4 id=\"posmotrim-ochen-interesnoe-rasshirenie-specsystemexitlistener\">\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043e\u0447\u0435\u043d\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 <code>SpecSystemExitListener<\/code><\/h4>\n<p>  <\/p>\n<p>\u0418\u043d\u043e\u0433\u0434\u0430 \u0432 \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f <code>System.exit()<\/code>, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c <code>graceful shutdown<\/code> \u0438\u043b\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438\u0437-\u0437\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0430 \u041e\u041f \u0441 \u043a\u043e\u0434\u043e\u043c <code>137<\/code>.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u0443 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e:<\/p>\n<p>  <\/p>\n<ul>\n<li><code>System.exit()<\/code> \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u044b\u043b \u0432\u044b\u0437\u0432\u0430\u043d<\/li>\n<li>\u041a\u043e\u0434 \u0432\u044b\u0445\u043e\u0434\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"kotlin\">@DoNotParallelize \/* 1 *\/ internal class KotestSystemExitTest : StringSpec() {     \/* 2 *\/     override fun extensions() = listOf(SpecSystemExitListener)      init {         \"Scenario: testing application try use System.exit\" {             \/* 3 *\/ shouldThrow&lt;SystemExitException> {             runApplicationWithOutOfMemoryExitCode() \/* 4 *\/         }.exitCode shouldBe 137 \/* 5 *\/         }     } }  private fun runApplicationWithOutOfMemoryExitCode(): Nothing = exitProcess(137)<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> \u0417\u0434\u0435\u0441\u044c \u0442\u043e\u0436\u0435 \u043d\u0435\u0442 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0439 \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 <code>@DoNotParallelize<\/code>.<\/li>\n<li><code>2<\/code> \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435.<\/li>\n<li><code>3<\/code> \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u0434 \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043e\u0442 Kotest \u2014 <code>SystemExitException<\/code>.<\/li>\n<li><code>4<\/code> \u0412\u043d\u0443\u0442\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 <code>Sysytem.exit()<\/code> == <code>exitProcess()<\/code>.<\/li>\n<li><code>5<\/code> \u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u043a\u043e\u0434 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f <code>137<\/code>.<\/li>\n<\/ul>\n<p>  <\/p>\n<h4 id=\"poslednee-na-segodnya-i-navernoe-samoe-populyarnoe-rasshirenie-constantnowtestlistener\">\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u043d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0438, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0441\u0430\u043c\u043e\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 <code>ConstantNowTestListener<\/code><\/h4>\n<p>  <\/p>\n<p>\u0427\u0430\u0441\u0442\u043e \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0434\u0430\u0442\u0430, \u043e\u0431\u044b\u0447\u043d\u043e \u0432 UTC. \u0418 \u0447\u0430\u0441\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a\u0430\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0434\u0430\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u0435\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0447\u0430\u0441\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0434\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0434\u0430\u0442\u0443 \u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u0443\u044e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f.<\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0440\u0435\u0448\u0430\u0435\u0442 \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>now()<\/code> \u0443 \u043b\u044e\u0431\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>Temporal<\/code>, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>LocalDate<\/code> \/ <code>ZonedDateTime<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">@DoNotParallelize internal class KotestNowTest : StringSpec() {      override fun extensions() = listOf(         \/* 1 *\/ ConstantNowTestListener&lt;LocalDate>(LocalDate.EPOCH),         \/* 2 *\/ ConstantNowTestListener&lt;LocalTime>(LocalTime.NOON)     )      init {         \"Scenario: date and time will be mocked, but dateTime not\" {             \/* 3 *\/             LocalDate.now() shouldBe LocalDate.EPOCH             LocalTime.now() shouldBe LocalTime.NOON              \/* 4 *\/             val localDateTimeNow = LocalDateTime.now()             delay(100)             LocalDateTime.now() shouldBeAfter localDateTimeNow         }     } }<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> \u0417\u0430\u043c\u0435\u043d\u044f\u0435\u043c <code>now()<\/code> \u0434\u043b\u044f \u043a\u043b\u0430\u0441\u0441\u0430 <code>LocalDate<\/code> \u2014 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c <code>LocalDate.EPOCH<\/code> (<code>01.01.1970<\/code>).<\/li>\n<li><code>2<\/code> \u0417\u0430\u043c\u0435\u043d\u044f\u0435\u043c <code>now()<\/code> \u0434\u043b\u044f \u043a\u043b\u0430\u0441\u0441\u0430 <code>LocalTime<\/code> \u2014 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c <code>LocalTime.NOON<\/code> (<code>12:00<\/code>).<\/li>\n<li><code>3<\/code> \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c <code>now()<\/code> \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/li>\n<li><code>4<\/code> \u041d\u043e \u043a\u043b\u0430\u0441\u0441 <code>LocalDateTime<\/code> \u0432\u0441\u0435 \u0435\u0449\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e-\u0441\u0442\u0430\u0440\u043e\u043c\u0443.<\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"integraciya-so-spring\">\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441\u043e Spring<\/h2>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u043c\u044b \u0438 \u0434\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u0434\u043e \u043a\u0443\u043b\u044c\u043c\u0438\u043d\u0430\u0446\u0438\u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0432\u0441\u0435 \u044d\u0442\u043e \u0437\u0430\u0442\u0435\u0432\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a <code>Kotest<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e <code>Spring Test<\/code> \u0438 <code>Spring Boot Test<\/code> \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>Kotest<\/code> \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f <code>unit<\/code> \/ <code>\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445<\/code> \/ <code>e2e<\/code> \/ <code>\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445<\/code> \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e <code>Spring Boot<\/code> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0435 \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u0447\u0435\u043c <code>Junit<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0410 \u0432 \u0447\u0430\u0441\u0442\u0438 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u0438 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u0441\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u0430\u0436\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u0435\u0435, \u043f\u043e \u043c\u043d\u0435\u043d\u0438\u044e \u0430\u0432\u0442\u043e\u0440\u0430.<\/p>\n<p>  <\/p>\n<h4 id=\"dobavlyaem-neobhodimye-zavisimosti-v-nash-gradle-proekt\">\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 \u043d\u0430\u0448 <code>Gradle<\/code> \u043f\u0440\u043e\u0435\u043a\u0442<\/h4>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">plugins {     id 'org.jetbrains.kotlin.jvm' version '1.7.10'     id 'org.jetbrains.kotlin.plugin.spring' version '1.7.10'     id 'org.springframework.boot' version '2.7.2' }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 <code>kotlin<\/code>, \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b Spring AOP \u0441 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u043c\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043a\u043b\u0430\u0441\u0441\u0430\u043c\u0438 \u043a\u043e\u0442\u043b\u0438\u043d\u0430 <code>kotlin.plugin.spring<\/code> \u0438 <code>spring boot<\/code> \u043f\u043b\u0430\u0433\u0438\u043d.<\/p>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u043c \u0443\u0434\u043e\u0431\u043d\u044b\u0439 <code>spring.dependency-management<\/code> \u0438\u0437 \u0441\u043e\u0441\u0442\u0430\u0432\u0430 <code>spring boot<\/code> \u043f\u043b\u0430\u0433\u0438\u043d\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 <code>BOM<\/code> \u0441 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a<br \/>  \u0438 \u043d\u0435 \u0437\u0430\u0431\u043e\u0442\u0438\u0442\u0441\u044f \u043e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0432 \u0431\u043b\u043e\u043a\u0435 <code>dependencies<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0412\u0435\u0440\u0441\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430 \u0441\u0430\u0439\u0442\u0435 <a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/current\/reference\/html\/dependency-versions.html\">docs.spring.io<\/a><\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">apply plugin: 'io.spring.dependency-management'<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">dependencies {     \/\/ \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f     implementation 'org.springframework.boot:spring-boot-starter-web'     implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'      \/\/ Sprint Boot Test     testImplementation 'org.springframework.boot:spring-boot-starter-test'     \/\/ HTTP \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f e2e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f     testImplementation 'io.rest-assured:rest-assured'      \/\/ JUnit5     testImplementation('org.junit.jupiter:junit-jupiter')     testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine')     testImplementation('org.junit.jupiter:junit-jupiter-params')      \/\/ Kotest     testImplementation platform('io.kotest:kotest-bom:5.4.1')     testImplementation 'io.kotest:kotest-runner-junit5'     \/\/ Spring + Kotest     testImplementation('io.kotest.extensions:kotest-extensions-spring:1.1.2') { exclude group: 'io.kotest' } }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u041e\u0431\u0440\u0430\u0449\u0430\u044e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0449\u0435\u0439:  <\/p>\n<ul>\n<li>\u0411\u0435\u0437 <code>jackson-module-kotlin<\/code> \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432 <code>data<\/code> \u043a\u043b\u0430\u0441\u0441\u044b <code>Kotlin<\/code>. \u0427\u0430\u0441\u0442\u043e \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/li>\n<li>\u0414\u0432\u0438\u0436\u043e\u043a \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f <code>junit-jupiter-engine<\/code> \u043d\u0435 \u043d\u0443\u0436\u0435\u043d \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 <code>testRuntimeOnly<\/code>.<\/li>\n<li><code>testImplementation platform('io.kotest:kotest-bom:5.4.1')<\/code> kotest \u043d\u0435\u0442 \u0441\u0440\u0435\u0434\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a <code>Spring Boot<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c <code>BOM<\/code>.<\/li>\n<li><code>kotest-extensions-spring<\/code> \u044d\u0442\u043e \u0446\u0435\u043b\u0435\u0432\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 <code>Kotest<\/code> \u0438 <code>Spring<\/code>, \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438 \u0432\u0435\u0434\u0435\u0442 \u0441\u0432\u043e\u0435 \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435.<\/li>\n<\/ul>\n<p>  <\/p><\/blockquote>\n<p>\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c <code>junit5<\/code> \u2014 \u043e\u043d \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0443\u0436\u0435\u043d \u043a\u0430\u043a \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 <code>kotest<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">test {     useJUnitPlatform()     systemProperty \"kotest.framework.dump.config\", \"true\" \/\/ \u0425\u043e\u0442\u0438\u043c \u043d\u0430\u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0434\u043b\u044f Kotest }<\/code><\/pre>\n<p>  <\/p>\n<h4 id=\"gotovim-konfiguraciyu-proekta\">\u0413\u043e\u0442\u043e\u0432\u0438\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 <code>SpringExtension<\/code> \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">object KotestProjectConfig : AbstractProjectConfig() {      override fun extensions() = listOf(SpringExtension) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0439 <code>Kotest<\/code> \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<br \/>  \u0415\u0441\u043b\u0438 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c <code>Spring<\/code> \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">class MyTestSpec : FunSpec() {     override fun extensions() = listOf(SpringExtension) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u0438\u043b\u0438 \u0438\u043d\u0430\u0447\u0435, \u043f\u043e\u0441\u043b\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0441\u043f\u0440\u0438\u043d\u0433\u043e\u0432\u044b\u0439 <code>TestContextManager<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u0432\u0441\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0438\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u0442\u0435\u0441\u0442\u0430, \u0434\u0430\u0436\u0435 \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0442\u0438\u043f\u0430 <code>@Autowired<\/code>.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0447\u0435\u0440\u0435\u0437 <code>Kotest<\/code> \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043a <code>ConstructorExtension<\/code> \u2014 <code>Spring<\/code> \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0435\u0433\u043e \u0438 \u0431\u0435\u0440\u0435\u0442 \u043d\u0430 \u0441\u0435\u0431\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">internal class MyTestSpec(propertyResolverInConstructor: PropertyResolver) : FunSpec()<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0443\u0442 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <code>propertyResolverInConstructor<\/code>\u0432\u043d\u0435\u0434\u0440\u044f\u0435\u0442\u0441\u044f \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u043b\u043e\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0439, \u043a\u0430\u043a \u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u0430 \u043d\u0435 \u0447\u0435\u0440\u0435\u0437 <code>setter<\/code>!<\/p>\n<p>  <\/p>\n<h4 id=\"chto-budem-testirovat\">\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c?<\/h4>\n<p>  <\/p>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c <code>Spring<\/code> \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0441 \u043e\u0434\u043d\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c <code>POST<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435.<\/p>\n<p>  <\/p>\n<p>\u0412\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">data class RequestDto(     val text: String? )<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0442\u0432\u0435\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">data class ResponseDto(     val code: Int,     val message: String )<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u0441\u0430\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440:<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">@RestController class ValidationController {      @PostMapping(\"\/validation\", consumes = [APPLICATION_JSON_VALUE], produces = [APPLICATION_JSON_VALUE])     fun sampleValidateEndpoint(@RequestBody request: RequestDto): ResponseDto =         when {             request.text == null -> ResponseDto(1, \"Null text\") \/* 1 *\/             request.text.isBlank() -> ResponseDto(2, \"Blank text\") \/* 2 *\/             else -> ResponseDto(0, \"Ok\") \/* 3 *\/         } }<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> \u0415\u0441\u043b\u0438 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0442\u0435\u043a\u0441\u0442 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442, \u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u043c <code>{ \"code\": 1, \"message\": \"Null text\" }<\/code><\/li>\n<li><code>2<\/code> \u0415\u0441\u043b\u0438 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0442\u0435\u043a\u0441\u0442 \u043f\u0443\u0441\u0442\u043e\u0439 \u0438\u043b\u0438 \u0438\u0437 \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432, \u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u043c <code>{ \"code\": 2, \"message\": \"Blank text\" }<\/code><\/li>\n<li><code>3<\/code> \u0415\u0441\u043b\u0438 \u0432 \u0442\u0435\u043a\u0441\u0442 \u0435\u0441\u0442\u044c, \u0442\u043e <code>{ \"code\": 0, \"message\": \"Ok\" }<\/code><\/li>\n<\/ul>\n<p>  <\/p>\n<h4 id=\"sozdaem-e2e-scenariy\">\u0421\u043e\u0437\u0434\u0430\u0435\u043c E2E \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439<\/h4>\n<p>  <\/p>\n<p>\u0412 \u0442\u0435\u0441\u0442\u0435 \u043c\u044b \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u043c \u043f\u043e\u0440\u0442\u0443, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u043a \u043d\u0435\u043c\u0443 <code>HTTP<\/code> \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b, \u2014 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 <strong>End 2 End<\/strong>.<\/p>\n<p>  <\/p>\n<p>\u0411\u0443\u0434\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c, \u043a\u0430\u043a \u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f, Data Driven Test \u043d\u0430 3 \u043d\u0430\u0431\u043e\u0440\u0430 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 BDD \u0441\u0442\u0438\u043b\u0435.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0442\u0430\u043a\u043e\u0439 \u0442\u0435\u0441\u0442 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0432 BDD \u043f\u043e\u0434\u0445\u043e\u0434\u0435 \u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435. \u0418 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0442\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f <code>Kotest<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0441\u0442\u0438\u043b\u0435\u0439 \u2014 \u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u0431\u0438\u0440\u0430\u044e <code>FreeSpec<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e \u0432\u0441\u0435\u0445 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0447\u0430\u0441\u0442\u044f\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u043b\u0438\u0431\u043e <code>StringSpec<\/code> \u0434\u043b\u044f \u043f\u043b\u043e\u0441\u043a\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0435\u0437 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u0438, \u043b\u0438\u0431\u043e <code>FreeSpec<\/code> \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0441 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e \u0438 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0431\u043b\u043e\u043a\u0430\u043c\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) \/* 1 *\/ internal class ValidationControllerKotestTest(     @Value(\"\\${local.server.port}\") private val localServerPort: String \/* 2 *\/ ) : FreeSpec() <\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c <code>SpringBootTest<\/code>, \u0442\u043e \u0435\u0441\u0442\u044c \u0433\u043e\u0432\u043e\u0440\u0438\u043c \u0442\u0435\u0441\u0442\u0443, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0430\u0440\u0442\u0435\u0440\u044b, \u043d\u043e \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u043c \u043f\u043e\u0440\u0442\u0443.<\/li>\n<li><code>2<\/code> \u0414\u043b\u044f \u0442\u0435\u0441\u0442\u0430 \u043d\u0443\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c \u043d\u043e\u043c\u0435\u0440 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u0430, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u042f \u0445\u043e\u0447\u0443 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u043b\u044e\u0431\u043e\u0439 <code>Bean<\/code> \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">internal class ValidationControllerKotestTest(   @Value(\"\\${local.server.port}\") private val localServerPort: String,   propertyResolverInConstructor: PropertyResolver \/* 1 *\/ ) : FreeSpec() <\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u044e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c <code>property<\/code> \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434\u044b <code>PropertyResolver<\/code> \u2014 \u0432\u043d\u0435\u0434\u0440\u044f \u044d\u0442\u043e\u0442 <code>Bean<\/code> \u0438 \u0432 \u0442\u0435\u0441\u0442\u0435 \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0435\u0433\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044e!<\/li>\n<\/ul>\n<p>  <\/p>\n<blockquote><p>? \u041d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0432 <code>Mir.Platform<\/code> \u0443 \u043d\u0430\u0441 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u044b \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u0447\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 <code>code review<\/code><\/p><\/blockquote>\n<p>\u0412 \u0431\u043b\u043e\u043a\u0435 <code>init<\/code> \u043e\u0444\u043e\u0440\u043c\u043b\u044f\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f \u043f\u0440\u044f\u043c\u043e \u043a\u0430\u043a \u0432 <code>Cucumber<\/code> \u0431\u0435\u0437 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0443\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438 \u043e\u0442\u0434\u0430\u0442\u044c \u043d\u0430 \u0440\u0435\u0432\u044c\u044e \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">init {     table(         headers(\"Text field\", \"Expected Code\", \"Expected Message\"), \/* 1 *\/         row(\"Hello\", 0, \"Ok\"), \/* 2 *\/         row(null, 1, \"Null text\"),         row(\"    \", 2, \"Blank text\")     ).forAll { text, expectedCode, expectedMessage ->          \"Scenario: Validation for text '$text'\" - { \/* 3 *\/              \"Given spring context injected successfully\" { } \/* 4 *\/              \"Given POST request prepared with text '$text'\" { } \/* 5 *\/              \"When request sent\" { }              \"Then response with body code $expectedCode and body message '$expectedMessage'\" { }         }     } }<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> \u041d\u0430\u0431\u043e\u0440\u044b \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u044f \u0431\u0443\u0434\u0443 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0432\u0438\u0434\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b. \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u043d\u0443\u0436\u043d\u044b \u0434\u043b\u044f \u0447\u0438\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u0434\u0430 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f.<\/li>\n<li><code>2<\/code> \u0422\u0440\u0438 \u043d\u0430\u0431\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u0442\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u0430.<\/li>\n<li><code>3<\/code> \u0411\u043b\u043e\u043a \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d 3 \u0440\u0430\u0437\u0430 \u0438 \u0432 \u043e\u0442\u0447\u0435\u0442\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a 3 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f.<\/li>\n<li><code>4<\/code> \u041f\u0440\u043e\u0432\u0435\u0440\u044e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u0440\u0430\u0431\u043e\u0442\u0443 <code>PropertyResolver<\/code><\/li>\n<li><code>5<\/code> \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 > \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 > \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0448\u0430\u0433\u043e\u0432:<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">\"Scenario: Validation for text '$text'\" - {      \"Given spring context injected successfully\" {         val appContextExample = testContextManager().testContext.applicationContext \/* 1 *\/          appContextExample.environment.getProperty(\"local.server.port\") shouldBe localServerPort \/* 2 *\/         propertyResolverInConstructor.getProperty(\"local.server.port\") shouldBe localServerPort \/* 3 *\/     }      \"Given POST request prepared with text '$text'\" {         body = RestAssured \/* 4 *\/             .with()             .log()             .all()             .contentType(MediaType.APPLICATION_JSON_VALUE)             .accept(MediaType.APPLICATION_JSON_VALUE)             .body(RequestDto(text))     }      \"When request sent\" {         post = body.post(\"http:\/\/localhost:$localServerPort\/validation\") \/* 5 *\/     }      \"Then response with body code $expectedCode and body message '$expectedMessage'\" {         post             .then()             .log()             .all()             .statusCode(200) \/* 6 *\/             .body(\"code\", Matchers.equalTo(expectedCode))             .body(\"message\", Matchers.equalTo(expectedMessage))     } }<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> <code>testContextManager()<\/code> \u043c\u0435\u0442\u043e\u0434 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0442\u0435\u0441\u0442\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0439 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 Spring <code>ContextManager<\/code>, \u0430 \u0432 \u043d\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u0438 <code>applicationContext<\/code><\/li>\n<li><code>2<\/code> \u0423\u0431\u0435\u0436\u0434\u0430\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043d\u0435\u0434\u0440\u0438\u043b \u043d\u0430\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u0442\u0435\u0441\u0442-\u043a\u043b\u0430\u0441\u0441\u0430.<\/li>\n<li><code>3<\/code> \u041a\u0430\u043a \u044f \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b \u0432\u044b\u0448\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c <code>propertyResolver<\/code> \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u043d\u044b\u0439 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435.<\/li>\n<li><code>4<\/code> \u0413\u043e\u0442\u043e\u0432\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>RestAssured<\/code><\/li>\n<li><code>5<\/code> \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441<\/li>\n<li><code>6<\/code> \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043e\u0442\u0432\u0435\u0442<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e \u0442\u0435\u0441\u0442 \u0433\u043e\u0442\u043e\u0432!<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e \u0432 Idea, \u0442\u043e \u0432\u044b\u0432\u043e\u0434 \u0445\u043e\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0438\u043c:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/vq\/a_\/is\/vqa_isvvard51rqsiuxvbjauk3w.png\" data-src=\"https:\/\/habrastorage.org\/webt\/vq\/a_\/is\/vqa_isvvard51rqsiuxvbjauk3w.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043d\u0430 \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>@DirtiesContext<\/code>. \u0423 \u043c\u0435\u043d\u044f \u0441\u0442\u0430\u0440\u0442 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e <strong>2.297<\/strong> \u0441\u0435\u043a\u0443\u043d\u0434\u044b<\/p>\n<p>  <\/p>\n<h2 id=\"sravnim-s-junit5\">\u0421\u0440\u0430\u0432\u043d\u0438\u043c \u0441 Junit5<\/h2>\n<p>  <\/p>\n<p>\u0412 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438 \u0434\u0430\u0436\u0435 \u0432 \u043e\u0434\u043d\u043e\u0439 <code>source-\u043f\u0430\u043f\u043a\u0435<\/code> \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0443\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0434\u0432\u0438\u0436\u043a\u0438, \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 <code>JunitPlatform<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0421\u0442\u0430\u0440\u044b\u0439 \u0434\u043e\u0431\u0440\u044b\u0439 <code>Junit5<\/code> \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 <em>E2E DataDriven<\/em> \u0442\u0435\u0441\u0442\u043e\u043c \u043d\u0430\u0448\u0435\u0433\u043e <code>Spring Boot<\/code> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">@ExtendWith(SpringExtension::class) \/* 1 *\/ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) \/* 2 *\/ internal class ValidationControllerJunitTest {      @Value(\"\\${local.server.port}\")     private val localServerPort = 0 \/* 3 *\/      @ParameterizedTest(name = \"Validation for {0}\")     \/* 4 *\/     @CsvSource( \/* 5 *\/         textBlock = \"\"\"       Text field | Expected Code | Expected Message        Hello      | 0             | Ok       null       | 1             | Null text       '   '      | 2             | Blank text\"\"\",          delimiter = '|', useHeadersInDisplayName = true, nullValues = [\"null\"]     )     fun testSampleGetEndpointTextNull(text: String?, expectedCode: Int, expectedMessage: String) {         RestAssured \/* 6 *\/             .with()             .log()             .all()             .contentType(MediaType.APPLICATION_JSON_VALUE)             .accept(MediaType.APPLICATION_JSON_VALUE)             .body(RequestDto(text))             .post(\"http:\/\/localhost:$localServerPort\/validation\")             .then()             .log()             .all()             .statusCode(200)             .body(\"code\", Matchers.equalTo(expectedCode))             .body(\"message\", Matchers.equalTo(expectedMessage))     } }<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 <code>SpringTest<\/code> \u043a \u0442\u0435\u0441\u0442\u0443. \u0412 <code>Kotest<\/code> \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u044d\u0442\u043e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0438 \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u0442\u0435\u0441\u0442\u0443.<\/li>\n<li><code>2<\/code> \u0421\u0442\u0430\u0440\u0442\u0443\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u043c \u043f\u043e\u0440\u0442\u0443<\/li>\n<li><code>3<\/code> \u0412\u043d\u0435\u0434\u0440\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u0442\u0430 \u0432 \u043f\u043e\u043b\u0435. \u041d\u043e \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u0442\u0442\u0435\u0440! \u0412 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 <code>Junit<\/code> \u0442\u0435\u0441\u0442\u0430 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f!<\/li>\n<\/ul>\n<p>  <\/p>\n<blockquote><p>\u2754 \u0410 \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 <code>val<\/code>?<br \/>  \u041f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 gradle-\u043f\u043b\u0430\u0433\u0438\u043d <code>kotlin.plugin.spring<\/code> \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u044d\u0442\u043e \u043f\u043e\u043b\u0435 \u043d\u0435 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u043c.<\/p><\/blockquote>\n<p>  <\/p>\n<ul>\n<li><code>4<\/code> \u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0442\u0435\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u043c<\/li>\n<li><code>5<\/code> \u0410 <code>@CsvSource<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0443\u044e DDT \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u0442\u043e\u0439, \u0447\u0442\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u043b\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0432 <code>Kotest<\/code> \u0441 \u0442\u0440\u0435\u043c\u044f \u043d\u0430\u0431\u043e\u0440\u0430\u043c\u0438<\/li>\n<li><code>6<\/code> \u0418 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e DSL RestAssured \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043e\u0442\u0432\u0435\u0442.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0410 \u0432\u043e\u0442 \u043a\u0430\u043a\u043e\u0439 \u0432\u044b\u0432\u043e\u0434 \u0438\u043c\u0435\u0435\u043c \u0432 \u043e\u043a\u043d\u0435 \u0441 \u0445\u043e\u0434\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/kw\/e0\/yf\/kwe0yfwqjjrzmkmu0hp_sjzug-w.png\" data-src=\"https:\/\/habrastorage.org\/webt\/kw\/e0\/yf\/kwe0yfwqjjrzmkmu0hp_sjzug-w.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u0441\u0442 <code>JUnit5<\/code> \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0435\u0435, \u0442\u0430\u043a \u043f\u043e\u0447\u0435\u043c\u0443 \u0436\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>Kotest<\/code> \u0434\u043b\u044f <strong>\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e<\/strong> \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. <\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u0447\u0435\u0440\u043a\u043d\u0443, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u2014 \u0432 \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u0430\u0445 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 <code>JUnit5<\/code>. <\/p>\n<p>  <\/p>\n<p>\u0410 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u0430\u0445 \u043d\u0430\u043c \u0432\u0430\u0436\u043d\u0430 \u043e\u0447\u0435\u043d\u044c \u0447\u0435\u0442\u043a\u0430\u044f \u0438 \u0433\u0438\u0431\u043a\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f \u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0440\u0430\u0437\u0431\u0438\u0442\u0430\u044f \u043d\u0430 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0431\u043b\u043e\u043a\u0438 \u2014 <code>Kotest<\/code> \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u0432 \u043d\u0430\u0448\u0435\u043c \u0442\u0435\u0445. \u0441\u0442\u0435\u043a\u0435.<\/p>\n<p>  <\/p>\n<blockquote><p><em>\u0418 \u0435\u0449\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435 \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0435:<\/em> <code>Spring Context<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u043d\u044f\u043b\u0441\u044f \u0434\u043b\u044f <code>Kotest<\/code> \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f \u0438 \u0434\u043b\u044f <code>Junit5<\/code>!<\/p><\/blockquote>\n<p>  <\/p>\n<h2 id=\"ostaetsya-otchetnost\">\u041e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0447\u0435\u0442\u043d\u043e\u0441\u0442\u044c<\/h2>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u043e\u0442\u0447\u0435\u0442\u043d\u043e\u0441\u0442\u044c. <\/p>\n<p>  <\/p>\n<p>\u0418 \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0442\u0435\u0441\u0442\u0430 \u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043b\u0435\u0433\u043b\u0430 \u0432 \u044d\u0442\u0443 \u043e\u0442\u0447\u0435\u0442\u043d\u043e\u0441\u0442\u044c&#8230;<\/p>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c <code>Allure<\/code> \u043e\u0442\u0447\u0435\u0442\u044b \u0432 \u0442\u0435\u0441\u0442\u044b \u0438 \u0437\u0430\u043e\u0434\u043d\u043e \u0432 <code>RestAssured<\/code>, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b. <\/p>\n<p>  <\/p>\n<p>\u0421\u0430\u043c\u043e \u0441\u043e\u0431\u043e\u0439, \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435.<\/p>\n<p>  <\/p>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442 <code>io.kotest.extensions:kotest-extensions-allure<\/code>, \u043d\u043e \u043e\u043d\u043e \u043d\u0430\u043c \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0441 \u0438\u044e\u043b\u044f 2022 \u0433\u043e\u0434\u0430 \u043f\u043e \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043a\u043e\u043d\u0435\u0446 \u0430\u0432\u0433\u0443\u0441\u0442\u0430 2022 \u0433\u043e\u0434\u0430 <strong>\u043d\u0435<\/strong> \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e \u0441 <code>Kotest > 5.4.0<\/code>, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u043d\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f <\/li>\n<li>\u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0442\u0435\u0441\u0442\u0430 \u0434\u043b\u044f <code>Data Driven<\/code> \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432<\/li>\n<li>\u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <code>Allure<\/code><\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041d\u043e \u0435\u0441\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435! <\/p>\n<p>  <\/p>\n<p>\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 <strong><a href=\"https:\/\/github.com\/kochetkov-ma\/kotest-allure\"><code>ru.iopump.kotest:kotest-allure<\/code><\/a><\/strong> \u2014 \u043e\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0432\u0441\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u043e \u0437\u0432\u0435\u0437\u0434\u043e\u0447\u043a\u043e\u0439 \u043e\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u044f <code>Kotest<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0432\u0435\u0440\u044f\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0432 <code>Gradle<\/code>, \u0430 \u0437\u0430\u043e\u0434\u043d\u043e \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0438 \u0434\u043b\u044f <code>RestAssured<\/code><\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">dependencies {   \/\/Allure   testImplementation 'io.qameta.allure:allure-rest-assured:2.18.1'   testImplementation 'ru.iopump.kotest:kotest-allure:5.4.1' }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432 \u043a\u043e\u0434\u0435\u2026 \u0410 \u0432 \u043a\u043e\u0434\u0435 \u0434\u043b\u044f <code>Kotest<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u043e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 <code>@AutoScan<\/code> \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.<\/p>\n<p>  <\/p>\n<p>\u0422\u043e\u0433\u0434\u0430 \u0434\u043b\u044f <code>RestAssured<\/code> \u2014 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">object KotestProjectConfig : AbstractProjectConfig() {      override suspend fun beforeProject() = RestAssured.filters(AllureRestAssured()) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u043d\u0430\u0431\u0440\u043e\u0441\u0430\u0435\u043c \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0435\u0441\u0442-\u043a\u043b\u0430\u0441\u0441 \u0432 <code>Mir.Platform<\/code><\/p>\n<p>  <\/p>\n<pre><code class=\"kotlin\">@Epic(\"Habr\") \/* 1 *\/ @Feature(\"Kotest\") \/* 2 *\/ @Story(\"Validation\") \/* 3 *\/ @Link(name = \"Requirements\", url = \"https:\/\/habr.com\/ru\/company\/nspk\/blog\/\") \/* 4 *\/ @KJira(\"KT-1\") \/* 5 *\/ @KDescription(   \"\"\" Kotest integration with Spring Boot. Also using Allure Listener for test reporting.     \"\"\" ) \/* 6 *\/ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) internal class ValidationControllerKotestTest<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> \u0412\u0435\u0440\u0445\u043d\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0438 \u0442\u0435\u0441\u0442\u043e\u0432<\/li>\n<li><code>2<\/code> \u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u043f\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438<\/li>\n<li><code>3<\/code> \u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u043f\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0438\u0441\u0442\u043e\u0440\u0438\u0438<\/li>\n<li><code>4<\/code> \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f<\/li>\n<li><code>5<\/code> \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043d\u043e\u043c\u0435\u0440 \u0437\u0430\u0434\u0430\u0447\u0438<\/li>\n<li><code>6<\/code> \u041c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e\u0435 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435, \u043f\u043e\u044f\u0441\u043d\u044f\u044e\u0449\u0435\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0432 \u0442\u0435\u0441\u0442\u0435 \/ \u043b\u043e\u0433\u0438\u043a\u0443 \/ \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0434\u043b\u044f \u0441\u0441\u044b\u043b\u043e\u043a \u0432 <code>allure.properties<\/code> \u0438 \u043f\u043e\u043b\u043e\u0436\u0438\u0442 \u0432 \u043f\u0430\u043f\u043a\u0443 <code>resources\/<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u043e <code>{}<\/code> \u043d\u043e\u043c\u0435\u0440 \u0437\u0430\u0434\u0430\u0447\u0438 \u0438 \u0432\u0435\u0441\u0442\u0438 \u0432 <code>youtrack.jetbrains.com<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">allure.link.jira.pattern=https:\/\/youtrack.jetbrains.com\/issue\/{}<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u044e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0432\u043e\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u044b, \u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043c \u0438\u043c\u0435\u043d\u0430 \u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u0430 \u0441\u0441\u044b\u043b\u043e\u043a.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043e\u0442\u0447\u0435\u0442\u0430 \u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0430 Allure \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 <code>AspectJ<\/code> \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c Gradle-\u043f\u043b\u0430\u0433\u0438\u043d:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">plugins {     id \"io.qameta.allure\" version \"2.10.0\" }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0423 \u043d\u0430\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0424\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 <code>Kotest<\/code> <strong>\u043f\u043e\u043a\u0430<\/strong> \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f Allure \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u043c, \u0442\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043d\u0430\u043c \u043d\u0435 \u043f\u043e\u0434\u043e\u0439\u0434\u0435\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">allureReport {   clean = true \/* 1 *\/ }  allure {   adapter {     autoconfigureListeners = false \/* 2 *\/     version = '2.18.1' \/* 3 *\/     frameworks {       junit5 {         enabled = false \/* 4 *\/       }     }   } }<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>1<\/code> \u0414\u043b\u044f \u0437\u0430\u0434\u0430\u0447\u0438 <code>allureReport<\/code> \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043e\u0447\u0438\u0441\u0442\u043a\u0443 \u043f\u0435\u0440\u0435\u0434 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u2014 \u0438\u043d\u0430\u0447\u0435 \u043e\u043d \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u043e\u0442\u0447\u0435\u0442 \u0443\u0436\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d<\/li>\n<li><code>2<\/code> \u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u043f\u043e\u0434 \u0424\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0438<\/li>\n<li><code>3<\/code> \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a Allure \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430<\/li>\n<li><code>4<\/code> \u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f <code>junit5<\/code> \u0438\u043d\u0430\u0447\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0435\u0439, \u0442\u0430\u043a \u043a\u0430\u043a <code>Kotest<\/code> \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u043c \u043a\u0430\u043a <code>Junit5<\/code><\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u0435\u0441\u0442\u044b \u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e Allure-\u043e\u0442\u0447\u0435\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">gradle test allureReport<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 Allure \u043e\u0442\u0447\u0435\u0442, \u0445\u043e\u0442\u044f \u0442\u0430\u043c \u0432\u0441\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/tb\/mg\/jm\/tbmgjmhtsvbwppcqqiavzlb5oxi.png\" data-src=\"https:\/\/habrastorage.org\/webt\/tb\/mg\/jm\/tbmgjmhtsvbwppcqqiavzlb5oxi.png\"\/><\/p>\n<p>  <\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u0438, \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0432\u0441\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b <a href=\"https:\/\/github.com\/kochetkov-ma\/pump-samples\/tree\/master\/qa-kotest-articles\/kotest-third\">qa-kotest-articles\/kotest-third<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u0430\u043a\u0438 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0441\u044f \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u0440\u043e <code>Kotest<\/code> \u2014 \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438 \u0432\u0441\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0430\u0441\u043f\u0435\u043a\u0442\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0438 \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f <code>Spring<\/code> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435. <\/p>\n<p>  <\/p>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043b\u044e\u0431\u0443\u044e, \u043d\u0435 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u0443\u044e \u043c\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 <code>Kotest<\/code>:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>kotest-extensions-testcontainers<\/code><\/li>\n<li>\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c <strong>HTTP<\/strong> \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0438 \u0432 <code>kotest-extensions-wiremock<\/code><\/li>\n<li>\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 <code>Kafka<\/code> \u0447\u0435\u0440\u0435\u0437 <code>kotest-extensions-embedded-kafka<\/code><\/li>\n<\/ul>\n<p>  <\/p>\n<h2>\u0420\u0435\u0441\u0443\u0440\u0441\u044b<\/h2>\n<p>  <\/p>\n<p>\u26a1 <a href=\"https:\/\/habr.com\/ru\/company\/nspk\/blog\/\">\u0411\u043b\u043e\u0433 \u041c\u0438\u0440 Plat.Form<\/a><\/p>\n<p>  <\/p>\n<p>\u26a1 <a href=\"https:\/\/habr.com\/ru\/post\/520380\/\">Kotlin. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0447\u0430\u0441\u0442\u044c 1). Kotest: \u041d\u0430\u0447\u0430\u043b\u043e<\/a><\/p>\n<p>  <\/p>\n<p>\u26a1 <a href=\"https:\/\/habr.com\/ru\/company\/nspk\/blog\/542754\/\">Kotlin. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0427\u0430\u0441\u0442\u044c 2). Kotest. Deep Diving<\/a><\/p>\n<p>  <\/p>\n<p>\u26a1 <a href=\"https:\/\/github.com\/kochetkov-ma\/pump-samples\/tree\/master\/qa-kotest-articles\/kotest-third\/src\">\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u0434\u0430<\/a><\/p>\n<p>  <\/p>\n<p>\u26a1 <a href=\"https:\/\/github.com\/kotest\/kotest\">Kotest GitHub<\/a><\/p>\n<p>  <\/p>\n<p>\u26a1 <a href=\"https:\/\/github.com\/kotest\/kotest-extensions-spring\">Kotest Spring GitHub<\/a><\/p>\n<p>  <\/p>\n<p>\u26a1 <a href=\"https:\/\/github.com\/kochetkov-ma\/kotest-allure\">Kotest Allure GitHub<\/a><\/p>\n<p>  <\/p>\n<p>? <a href=\"https:\/\/kotest.io\/docs\/quickstart\">\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f Kotest<\/a><\/p>\n<p>  <\/p>\n<p>? <a href=\"https:\/\/kotlinlang.org\/docs\/home.html\">Kotlin Lang<\/a><\/p>\n<p>  <\/p>\n<p>? <a href=\"https:\/\/junit.org\/junit5\/docs\/current\/user-guide\/\">JUnit5<\/a><\/p>\n<p>  <\/p>\n<p>? <a href=\"https:\/\/docs.gradle.org\/current\/userguide\/java_testing.html\">Gradle Testing<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/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\/company\/nspk\/blog\/685330\/\"> https:\/\/habr.com\/ru\/company\/nspk\/blog\/685330\/<\/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-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/4u\/ri\/zl\/4urizlf0negicujw9_d9qhoafia.jpeg\" alt=\"Kotest\" data-src=\"https:\/\/habrastorage.org\/webt\/4u\/ri\/zl\/4urizlf0negicujw9_d9qhoafia.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u043d\u0430 <strong>Kotlin<\/strong> \u0438 \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 <strong>Kotest<\/strong><\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f <code>Kotest<\/code>:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0427\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435<\/li>\n<li>\u041a\u0430\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b<\/li>\n<li>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0432 <code>Kotest<\/code> <\/li>\n<li>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f<\/li>\n<li>\u041f\u0440\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f <strong>Spring<\/strong><\/li>\n<li>\u0423\u0433\u043b\u0443\u0431\u043b\u044e\u0441\u044c \u0432 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e <strong>Kotest<\/strong> \u0438 <strong>Spring Boot Test<\/strong><\/li>\n<li>\u0421\u0440\u0430\u0432\u043d\u044e \u0441 <strong>Junit5<\/strong><\/li>\n<li>\u0418 \u043d\u0430 \u0437\u0430\u043a\u0443\u0441\u043a\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u044e \u043e\u0442\u0447\u0435\u0442\u044b <strong>Allure<\/strong><\/li>\n<\/ul>\n<p>  <\/p>\n<blockquote><p>\u26a0\ufe0f\u0411\u0443\u0434\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432.<\/p><\/blockquote>\n<p>\u0412\u0441\u0435 \u0447\u0430\u0441\u0442\u0438 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0430:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/520380\/\">Kotlin. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0447\u0430\u0441\u0442\u044c 1). Kotest: \u041d\u0430\u0447\u0430\u043b\u043e<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/company\/nspk\/blog\/542754\/\">Kotlin. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0427\u0430\u0441\u0442\u044c 2). Kotest. Deep Diving<\/a><br \/>\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-339283","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/339283","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=339283"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/339283\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=339283"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=339283"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=339283"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}