{"id":7967,"date":"2021-09-22T04:59:59","date_gmt":"2021-09-22T04:59:59","guid":{"rendered":"https:\/\/berg-software.com\/?p=7967"},"modified":"2022-07-12T13:07:41","modified_gmt":"2022-07-12T13:07:41","slug":"gaitling-performance-tests-integration-gitlab-ci-cd-pipeline","status":"publish","type":"post","link":"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/","title":{"rendered":"Performance tests &#038; integration into GitLab CI\/CD pipeline (w\/ Gatling)"},"content":{"rendered":"<p>[et_pb_section fb_built=&#8221;1&#8243; fullwidth=&#8221;on&#8221; _builder_version=&#8221;4.4.1&#8243;][et_pb_fullwidth_post_title meta=&#8221;off&#8221; featured_placement=&#8221;background&#8221; _builder_version=&#8221;4.7.7&#8243; title_font=&#8221;||||||||&#8221; title_text_color=&#8221;#ff6317&#8243; title_font_size=&#8221;3.5em&#8221; meta_font=&#8221;|300|||||||&#8221; meta_text_color=&#8221;#ffffff&#8221; meta_font_size=&#8221;1em&#8221; background_enable_color=&#8221;off&#8221; use_background_color_gradient=&#8221;on&#8221; background_color_gradient_start=&#8221;rgba(248,248,248,0.85)&#8221; background_color_gradient_end=&#8221;rgba(248,248,248,0.75)&#8221; background_color_gradient_overlays_image=&#8221;on&#8221; min_height=&#8221;20vh&#8221; height=&#8221;400px&#8221; custom_padding=&#8221;6vh||6vh||false|false&#8221; global_module=&#8221;403&#8243; locked=&#8221;off&#8221;][\/et_pb_fullwidth_post_title][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; admin_label=&#8221;intro&#8221; _builder_version=&#8221;4.4.6&#8243; custom_padding=&#8221;|||0px||&#8221; locked=&#8221;off&#8221;][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.4.6&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>When continuous development and delivery of features are performed at very high rates, the system performance must stay within defined constraints. Here&#8217;s how we developed and integrated <a href=\"https:\/\/gatling.io\" target=\"_blank\" rel=\"noopener noreferrer\">Gatling<\/a> performance tests into the\u00a0<a href=\"https:\/\/about.gitlab.com\" target=\"_blank\" rel=\"noopener noreferrer\">GitLab<\/a> CI\/CD pipeline.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>Covered in this article:<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<ul>\n<li>What tools to use to run the performance test<\/li>\n<li>How to develop the performance test<\/li>\n<li>How to set up the GitLab pipeline<\/li>\n<li>Which endpoints to test, on which infrastructure<\/li>\n<li>Preparing data for the tests<\/li>\n<\/ul>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;2em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||10px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"introduction\">Introduction<\/h2>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]This article is an opinionated guide on how we developed and integrated our performance tests into our CI\/CD pipeline. This is by no means the only way or the best way to do it \u2013 we just want to share our approach and the challenges we faced. [\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>Nonfunctional requirements<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]Each application must fulfill certain requirements not related to the business needs but defined as constraints within which the system must run. These are called nonfunctional requirements. Some examples: performance constraints, when a certain number of concurrent users must be supported; and the response time between some defined limits. Other examples refer to the availability of the system &#8211; usually defined as percent of uptime out of total time that is affected by deployments and maintenance. Reliability, scalability and maintainability are other examples.[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>A bit about the application to test<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>The system to test is a collection of microservices running on <a href=\"https:\/\/about.gitlab.com\" target=\"_blank\" rel=\"noopener noreferrer\">Open Telekom Cloud<\/a> provider, in a high availability configuration having the persistence assured by <a href=\"https:\/\/www.mysql.com\" target=\"_blank\" rel=\"noopener noreferrer\">MySql<\/a> relational databases. The application is also interconnected with other systems like <a href=\"https:\/\/www.sap.com\/index.html\" target=\"_blank\" rel=\"noopener noreferrer\">SAP<\/a>, <a href=\"https:\/\/www.salesforce.com\/de\/?ir=1\" target=\"_blank\" rel=\"noopener noreferrer\">SalesForce<\/a>, and Enterprise Content Management System via rest interfaces, hooks, and files.<\/p>\n<p>Infrastructure as a code approach is used to spin up the servers and services using <a href=\"https:\/\/www.terraform.io\" target=\"_blank\" rel=\"noopener noreferrer\">Terraform<\/a> and <a href=\"https:\/\/www.ansible.com\" target=\"_blank\" rel=\"noopener noreferrer\">Ansible<\/a>. <a href=\"https:\/\/www.docker.com\" target=\"_blank\" rel=\"noopener noreferrer\">Docker<\/a> is used to package the application in multiple containers.<\/p>\n<p>CI\/CD is set up with GitLab.<\/p>\n<p>The tech stack mainly consists of <a href=\"https:\/\/www.java.com\/en\/\" target=\"_blank\" rel=\"noopener noreferrer\">Java<\/a> with <a href=\"https:\/\/spring.io\/projects\/spring-boot\" target=\"_blank\" rel=\"noopener noreferrer\">SpringBoot<\/a> and <a href=\"https:\/\/hibernate.org\" target=\"_blank\" rel=\"noopener noreferrer\">Hibernate<\/a>, <a href=\"https:\/\/hazelcast.com\" target=\"_blank\" rel=\"noopener noreferrer\">Hazelcast<\/a>, <a href=\"https:\/\/www.jhipster.tech\" target=\"_blank\" rel=\"noopener noreferrer\">JHipster<\/a>, <a href=\"https:\/\/angular.io\" target=\"_blank\" rel=\"noopener noreferrer\">Angular<\/a> with <a href=\"https:\/\/www.typescriptlang.org\" target=\"_blank\" rel=\"noopener noreferrer\">Typescript<\/a>, and also <a href=\"https:\/\/www.docker.com\" target=\"_blank\" rel=\"noopener noreferrer\">Docker<\/a> and <a href=\"https:\/\/kubernetes.io\" target=\"_blank\" rel=\"noopener noreferrer\">K8s<\/a>.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>What are performance tests?<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]The performance tests are automated tests running against the application under test, deployed on certain infrastructure to verify whether the performance parameters like response time and throughput remain within the defined limits under the supported load. [\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>The tools we used<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>For running the performance tests, we used <a href=\"https:\/\/gatling.io\" target=\"_blank\" rel=\"noopener noreferrer\">Gatling<\/a>, for its easy-to-use capability, good integration with CI\/CD tools and DevOps processes, and for the out of the box reporting.<\/p>\n<p>Gatling recorder available in Chrome was sometimes used as a starting point for developing test scenarios.<\/p>\n<p><a href=\"https:\/\/www.scala-lang.org\" target=\"_blank\" rel=\"noopener noreferrer\">Scala<\/a> was used to write the performance test scenarios and <a href=\"https:\/\/gradle.org\" target=\"_blank\" rel=\"noopener noreferrer\">Gradle<\/a> was our build tool.<\/p>\n<p><a href=\"https:\/\/www.docker.com\" target=\"_blank\" rel=\"noopener noreferrer\">Docker<\/a> was used to package our application as containers and <a href=\"https:\/\/about.gitlab.com\" target=\"_blank\" rel=\"noopener noreferrer\">Gitlab<\/a> was used for the CI\/CD pipelines with our configured runners.<\/p>\n<p>We used the <a href=\"https:\/\/spockframework.org\" target=\"_blank\" rel=\"noopener noreferrer\">Spock framework<\/a> with test scenarios written in <a href=\"https:\/\/groovy.apache.org\" target=\"_blank\" rel=\"noopener noreferrer\">Groovy<\/a> to prepare the test data.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>Why integrate performance tests into the CI\/CD pipeline?<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>It is important to make sure that the system performance remains within the defined constraints when continuous development and delivery of features are done at a very high rate.<\/p>\n<p>If the tests are failing, we know that some of the new code broke the performance constraints. Basically, the automated performance tests are run on every merge of a feature branch into certain environment branches. This way we have the confidence, before deploying the new version in production, that the performance for the sensitive or covered scenarios was not affected.<\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;2em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||10px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"introductiontogatling\">Introduction to Gatling<\/h2>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>Recording mode<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]The recorder can be started from the gatling bundle. It acts as a proxy between the browser and the server. [\/et_pb_text][et_pb_gallery gallery_ids=&#8221;7986&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221; custom_padding=&#8221;||35px||false|false&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]In the recorder, you must define the local proxy port where the browser must connect. The next step is to set the proxy server to access the internet via the localhost and the above-defined port. In Chrome you should navigate to Settings->Advanced->System->Open your computer proxy settings->Use a proxy server and enter the below settings.[\/et_pb_text][et_pb_gallery gallery_ids=&#8221;7988&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221; custom_padding=&#8221;||35px||false|false&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>This screen depends on the used operating system. Afterward, the browser should connect to this port.<\/p>\n<p>While the user navigates in the browser, the recorder records the request and pauses and at the end, it generates the simulation code. There are filters that can be defined to filter out those requests &#8211; for instance, all requests for CSS files. Also, SSL certificates can be provided or generated on the fly for the HTTPS mode.<\/p>\n<p>The generated code can be used as a starting point for developing the performance simulation, but it has to be reworked to be more maintainable, to ignore the not-needed requests, and to make the right correlations and abstractions.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>Simulations<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>The entry point of a performance test is a simulation. In a single run, the simulations to be executed can be configured. The simulation is the equivalent of a test case in the popular Junit library. It has setup and tear-down methods, but also helper methods for doing assertions and storing global values.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family: monospace;\">class MyInteractionsTest extends Simulation {\n\u00a0\n  val context: LoggerContext = LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext]\n  \/\/ Log all HTTP requests\n  context.getLogger(\"io.gatling.http\").setLevel(Level.valueOf(\"TRACE\"))<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]We defined one simulation by extending the base class, and set up the logging to trace the content of all http requests.[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">val httpConf = http\n  .baseUrl(PerfConstants.baseURLServer)\n  .inferHtmlResources()\n  .header(&quot;Origin&quot;, PerfConstants.baseURLServerWeb)\n  .acceptHeader(&quot;application\/json, text\/plain, application\/hal+json, application\/problem+json, *\/*&quot;)\n  .acceptEncodingHeader(&quot;gzip, deflate&quot;)\n  .acceptLanguageHeader(&quot;en,en-US;q=0.9,ro-RO;q=0.8,ro;q=0.7,de;q=0.6&quot;)\n  .connectionHeader(&quot;keep-alive&quot;)\n  .userAgentHeader(&quot;Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/71.0.3578.98 Safari\/537.36&quot;)\n  .disableWarmUp\n  .silentResources \/\/ Silence all resources like css or css so they don't clutter the results<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>Here we are configuring the HTTP protocol. We set up the HTTP headers with the expected values simulating the browser requests. The origin header is set to the provided server URL to avoid CORS issues. The static resources, like CSS files, and their failures are generating a lot of noise, so we want to disable the reporting for them via the silentResources flag.<\/p>\n<p>Inferring the HTML resources means to mimic the browser behavior of loading async the embedded resources like scripts, links, images, frames, objects, and so on.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family: monospace;\">val headers_http_authenticated = Map(\n  \"Content-Type\" -&gt; \"\"\"application\/json\"\"\",\n  \"Accept\" -&gt; \"\"\"application\/json, application\/hal+json, application\/problem+json\"\"\",\n  \"Authorization\" -&gt; \"${access_token}\",\n)<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>For different requests, we might need different headers. The above variable contains the headers for an authenticated request. The access token is provided as a value for the authorization header. The token was previously saved by a login request in a virtual user session via a mechanism called checks. The checks are used to validate the requests and extract values that can be later reused.<\/p>\n<p>One such login request can look like this:<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family: monospace;\">object Login {\n\u00a0\n  val headers_http_authentication = Map(\n    \"Content-Type\" -&gt; \"\"\"application\/json\"\"\",\n    \"Accept\" -&gt; \"\"\"application\/json, application\/hal+json, application\/problem+json\"\"\",\n  )\n\u00a0\n  val login =\n    exec(http(\"Authentication\")\n      .post(\"\/auth\/token\")\n      .headers(headers_http_authentication)\n      .body(StringBody(\"\"\"{\"username\":\"adm@project.com\", \"password\":\"*****\"}\"\"\"))\n      .check(status.is(PerfConstants.HTTP_STATUS_OK))\n      .check(header(\"Authorization\").saveAs(\"access_token\"))\n    ).exitHereIfFailed\n}<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>There is a login request object with a header for not authenticated users, not containing any tokens.<\/p>\n<p>Via the exec method, an HTTP post call is executed to the \/auth\/token endpoint providing the credentials in the body. The check constructs are validating the response status and are saving the access token received back in the authorization response header.<\/p>\n<p>The request can be executed as part of a scenario via a fluent API:<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">val scn = scenario(&quot;My interactions&quot;)\n   .exec(Login.login).exitHereIfFailed<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]A typical scenario has many requests defined in sequence.[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">val scn = scenario(&quot;My interactions&quot;)\n  .exec(http(&quot;First unauthenticated request&quot;)\n    .get(&quot;\/auth\/user&quot;)\n    .headers(headers_http)\n    .check(status.is(401))\n  ).exitHereIfFailed\n  .pause(3)\n  .exec(Login.login\n  ).exitHereIfFailed\n  .pause(2)\n  .exec(http(&quot;Authenticated request&quot;)\n    .get(&quot;\/auth\/user&quot;)\n    .headers(headers_http_authenticated)\n    .check(status.is(200)))\n  .pause(3)\n  .exec(NavigationTree.navigationTree)\n  .exec(MyInteractions.myInteractions)<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>After each request, checks can be performed, then exit if the conditions are not matching. Also, breaks can be injected to simulate a human user.<\/p>\n<p>The other scenario requests are looking similar to the login request but using different HTTP methods and checks.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">val navigationTree =\n  exec(http(&quot;Navigation EndPoints&quot;)\n    .get(PerfConstants.baseURLServer + &quot; \/navigationTree &quot;)\n    .headers(headers_http_authenticated)\n    .check(status.is(PerfConstants.HTTP_STATUS_OK))\n    .check(jsonPath(&quot;$.mainObjects[0].mainObject.aid&quot;).saveAs(&quot;firstOrder&quot;)))\n    .pause(PerfConstants.PAUSE_BETWEEN_REQ_IN_SEC)<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>There is a get request performed for an authenticated user, and the value is saved from the parsed JSON response in the virtual session variable called firstOrder.<\/p>\n<p>Each scenario has a setup phase, where the number of concurrent users and the ramp-up period are defined.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family: monospace;\">setUp(scn.inject(rampUsers(20) during (2 seconds))).protocols(httpConf)<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>In our case, 20 users are running the same scenario, and all are starting to create the first request in a 2 seconds interval. This means that after two seconds we will have at least 20 requests in progress.<\/p>\n<p>The scenario execution starts with the construct:<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">scenario(&quot;My navigation&quot;).exec(scn)<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>Expected thresholds<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>Expected response\/time thresholds can be defined globally for all requests or scenarios, but also for individual requests. The values must also take into consideration the infrastructure on which the tests are running and must be adjusted accordingly. Usually, the production infrastructure is more powerful than in the other environments. It was not an easy task to define the right values that also give us the expected ones in production.<\/p>\n<p>In the scenario setup phase also, the expected thresholds are defined:<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">setUp(scn.inject(rampUsers(20) during (2 seconds))).protocols(httpConf)\n  \/\/ Assert that every request has no more than 1% of failing requests\n  .assertions(forAll.failedRequests.percent.lte(1))\n  \/\/ Assert that the max response time of all requests is less than 5000 ms\n  .assertions(global.responseTime.max.lt(PerfConstants.MAX_RESPONSE_TIME_MS))\n  \/\/ Assert that the max response time of authentication requests is less than 3000 ms\n  .assertions(details(&quot;Authentication&quot;).responseTime.max.lt(PerfConstants.MAX_RESPONSE_TIME_AUTH_MS))\n  \/\/ Assert that the max response time of the navigation tree requests is less than 5000 ms\n  .assertions(details(&quot;Navigation tree&quot;).responseTime.max.lt(PerfConstants.MAX_RESPONSE_TIME_MS))\n  \/\/ Assert that the max response time of the my interactions requests is less than 5000 ms\n  .assertions(details(&quot;My interactions&quot;).responseTime.max.lt(PerfConstants.MAX_RESPONSE_TIME_MS))<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>One can do assertions for all requests of certain types, like failed request with the construct forAll.<\/p>\n<p>Assertions can be also done for all requests of any type with the construct global.<\/p>\n<p>For a particular request identified by the path, assertions can be made with the statement details(&#8220;request group \/ request path&#8221;).<\/p>\n<p>More assertions can be made on metrics such as the number of successful requests or the number of requests per second. Count or percentage values are available for comparison, while multiple conditions can be chained together. Comparison operators like between, around, and deviatesAround(target, percent) are available.<\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;2em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||10px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"setupthegitlabpipeline\">Setup the GitLab pipeline<\/h2>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>The pipeline is configured in the .gitlab-ci.yml file residing in the performance test project root.<\/p>\n<p>There is a single stage called test.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">stages:\n  - test<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>Docker image to use<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>One challenge we had was to find a docker image with all the needed Scala and Gatling libraries ready to be used without too much struggle. The GitLab runner should be able to pull this image, check out the code and launch the tests via a bash script.<\/p>\n<p>After several tries, we found the image koosiedemoer\/netty-tcnative-alpine that worked in our environment.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">perftest-master:\n  image: koosiedemoer\/netty-tcnative-alpine\n  stage: test<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>Execution trigger<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>There are two events that are causing the performance tests to run.<\/p>\n<p>One event is by doing a commit for the performance test project into our master branch.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">perftest-master:\n\u2026\n  only:\n    - master\n  except:\n    variables:\n      - $EXECUTE_TEST_FOR_ENVIRONMENT =~ \/^TEST\/<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>The step is executed only on the master branch when the environment variable EXECUTE_TEST_FOR_ENVIRONMENT is not defined or does not start with TEST. The variable is used to identify if an external trigger caused the execution &#8211; in case we need some different action\/config to perform.<\/p>\n<p>The other event is when called externally, after a certain step in another project pipeline.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">perftest-master:\n  stage: perftest\n  image: registry.gitlab.com\/finestructure\/pipeline-trigger\n  script:\n    - apk --no-cache add bash curl\n    - .\/ci\/bin\/perf-trigger.sh\n  tags:\n    - perftrigger\n  only:\n    - master<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>In a microservice project, in the GitLab CI pipeline config file a perftest stage is defined that pulls the pipeline-trigger docker image, installs the required packages, and executes the checked-out script perf-trigger.sh.<\/p>\n<p>This step is only executed when there is a commit on the master branch, and only after the previous pipeline stages are executed.<\/p>\n<p>The bash file contains something like:<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">trigger -a ${APP_GITLABTRIGGER_APITOKEN} -p ${APP_GITLABTRIGGER_PERFTESTTOKEN} -t ${branch} ${APP_GITLABTRIGGER_PERFTESTID} -e EXECUTE_TEST_FOR_ENVIRONMENT=TEST<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>The docker image contains the trigger command where GitLab tokes are provided, the target pipeline, the branch, and environment variables.<\/p>\n<p>In the performance test project, another stage can be defined only for the external trigger.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">perftest-master-ext:\n\u2026\nonly:\n    - master\nonly:\n  variables:\n    - $EXECUTE_TEST_FOR_ENVIRONMENT =~ \/^TEST\/<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]This time, the execution happens only if the branch is master and the variable is provided with the given value.[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>Execution setup<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">perftest-master:\n\u2026\n  script:\n    - apk --no-cache add bash\n    - .\/bin\/testperf.sh &quot;https:\/\/apistage.domain.net&quot;\n  tags:\n    - perftests\n  artifacts:\n    when: always\n    paths:\n      - build\/reports\/gatling\/*\n    expire_in: 1 week\n\u2026<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>In the script section, the missing packages are installed in the running container and the testperf.sh bash file is executed passing the stage environment as base API URL.<\/p>\n<p>The tag identifies the label for the GitLab runner that will execute the tests.<\/p>\n<p>The artifacts section configures the destination for saving the reports, and how long to keep them available for download.<\/p>\n<p>The bash file starts the Gradle command for running the test against the provided environment:<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">.\/gradlew gatlingRun -DbaseURL=${1}<\/pre>\n<p>[\/et_pb_text][et_pb_text admin_label=&#8221;in the gradle.build&#8221; _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>In the gradle.build file we are using the Gatling plugin and configure which tests to run and where to store the reports like in the following:<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">plugins {\n   id &quot;com.github.lkishalmi.gatling&quot; version &quot;3.0.2&quot;\n}\n\u2026\napply plugin: &quot;com.github.lkishalmi.gatling&quot;\n..\ngatling {\n\u2026\n\tsimulations = { include &quot;**\/*Test.scala&quot; }\n}\ntask testReport(type: TestReport) {\n    destinationDir = file(&quot;$buildDir\/reports\/tests&quot;)\n    reportOn test\n}\n\u2026<\/pre>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;2em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||10px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"preparing_the_data_and_the_infrastructure\">Preparing the data and the infrastructure for running the tests<\/h2>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>On which systems to execute the tests<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>There are at least two ways to do it. One way is to spin up a new environment and deploy the application on that clean environment with a well-defined configuration and capacity. Another way is to run the performance test on an existing environment with a fixed capacity and known configuration.<\/p>\n<p>You can also run the tests from time to time on production if you can afford to scale it or to find a time slot (maintenance window) when the users are not disturbed.<\/p>\n<p>We have chosen to run the performance against our staging environment because this is comparable with our production environment, and because we didn\u2019t want to wait for spinning up another clean environment. Also, the production users are not affected by running the tests often.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>Which endpoints to test<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>Each application has its own specifics and solves clear business needs. The most used business scenarios must be tested to make sure that the application stays in the agreed performance parameters. Also, one must consider the activities with the most risk of affecting the performance.<\/p>\n<p>Another approach would be to use monitoring tools to track the user activity, then analyze the critical points and the response times of the application, in order to decide what performance tests to write.<\/p>\n<p>We used both approaches and identified good candidates such as the authentication endpoints, authorization checking, some heavy lists of resources, and part of business logic.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font=&#8221;|600|||||||&#8221; header_3_font_size=&#8221;1.2em&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||5px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h3>Populating the data<\/h3>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>The data for the performance test can be a backup of the production database that can be restored in a reasonable amount of time.<\/p>\n<p>In case an existing environment is used for running the performance test, then some test users can authenticate and perform the scenarios.<\/p>\n<p>In our case, we are using the test users and data created by our integration tests. This is a prerequisite. Our integration tests are developed in Groovy using the Spook framework and are executing HTTP requests calling our REST APIs to populate the data.<\/p>\n<p>Spook tests can be written like the popular JUnit tests. There is a base class to extend called Specification that provides helper methods for mocking, stubbing, and spying. It is equivalent to a test case of Junit.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">class BaseSpec extends Specification {\n&nbsp;\n@Shared\npublic static HttpBuilder client<\/pre>\n<p>[\/et_pb_text][et_pb_text admin_label=&#8221;in the gradle.build&#8221; _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>Groovy sort of HTTP client is used for executing the API calls. The client is configured with a helper serialization library called JsonSlurper. The methods can be executed in order if we are using the @Stepwise annotation.<\/p>\n<p>There are setup and cleanup methods executed before every test method and setupSpec and cleanupSpec executed before and after every specification.<\/p>\n<p>One sample of setup method can initialize the HTTP client and login the admin user.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">def setupSpec() {\n    client = HttpBuilder.configure {\n    request.uri = BASE_URL_SERVER\n    request.setContentType('application\/json')\n    response.success { resp, data -&gt;\n     if (data != null){\n     }\t\n    }\n    \u2026\n    loginAs(admin)\n}<\/pre>\n<p>[\/et_pb_text][et_pb_text admin_label=&#8221;in the gradle.build&#8221; _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]A test method is written in the behavior-driven development style with the structure given-when-then.[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">def 'give ROLE_ADMIN privilege to the user'() {\n    given: 'a valid ADMIN privilege'\n    def privilege = [\n            scope   : 'RESOURCE',\n            key     : 'ROLE_ADMIN',\n            user    : [\n                    aid: userAid\n            ],\n            role    : [\n                    aid: ROLE_ADMIN_LICENSE\n            ],\n            resource: [\n                    aid: ROOT_COMPANY_AID\n            ]\n    ]\n&nbsp;\n    when: 'I post the privilege'\n    def response = client.post {\n        request.uri.path = '\/privileges'\n        request.body = privilege\n    }\n&nbsp;\n    then: 'the privilege was created'\n    assertResponseStatus(response, 201)\n}\n&nbsp;<\/pre>\n<p>[\/et_pb_text][et_pb_text admin_label=&#8221;in the gradle.build&#8221; _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>A privilege request is created, and an HTTP POST is sent to the server. In the end, the 201-HTTP status is checked, but it can check also the structure of the response.<\/p>\n<p>Multiple specs can be grouped in a test suite and executed at once.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">@RunWith(Suite.class)\n@Suite.SuiteClasses(\n        [\n                AnInitTestSuiteSpec,\n                AnotherWorkflowSpec\n\t]\n)\nclass TestSuite {\n}<\/pre>\n<p>[\/et_pb_text][et_pb_text admin_label=&#8221;in the gradle.build&#8221; _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]The gradle build part for executing the test suites is simple and can pass additional parameters:[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family:monospace;\">test{\n    systemProperty &quot;target&quot;, findProperty(&quot;target&quot;)\n    systemProperty &quot;targetServer&quot;, findProperty(&quot;targetServer&quot;)\n    testLogging {\n        exceptionFormat = 'full'\n    }\n    filter {\n        \/\/specific test method\n        includeTestsMatching &quot;specs.TestSuite&quot;\n    }\n}<\/pre>\n<p>[\/et_pb_text][et_pb_text admin_label=&#8221;in the gradle.build&#8221; _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]In conclusion, running a test suite that creates our performance test data works for us.[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;2em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||10px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"performance_tests_reports\">Performance tests reports<\/h2>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>Gatling creates a nice set of reports after running the scenarios. In the charts we can see things like response time, requests per second, throughput, mean times, and percentiles distributed over time and users. With some of the charts, one can interact and show additional info as a tooltip or zoom in and out the time interval. I will explain some of them when running different scenarios in the following.<\/p>\n<p>[\/et_pb_text][et_pb_gallery gallery_ids=&#8221;7990&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221; custom_padding=&#8221;||35px||false|false&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]Here we have executed a scenario of around 200 requests with 20 users. All were successful, around 75 were executed under 800ms, 25 requests were between 800 ms and 1200 ms, while the rest of them, around 95 were above 1200 ms.[\/et_pb_text][et_pb_gallery gallery_ids=&#8221;7992&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221; custom_padding=&#8221;||35px||false|false&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]In the scenarios, we can define performance assertions to be checked and reported in the above table. Multiple requests were executed within a scenario, and we defined the constraints to have max 1% of failed requests of different types. Another constraint was to have a max response time of any request under 15 seconds. Also, for particular requests, we defined that the response time to be under 15 seconds. We can see that some of the assertions failed. [\/et_pb_text][et_pb_gallery gallery_ids=&#8221;7994&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221; custom_padding=&#8221;||35px||false|false&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]We can name each request and have the minimum, the mean, and maximum time reported for each one, categorized in percentiles of all requests. Here 2 users executed the scenario in parallel, with the above steps.[\/et_pb_text][et_pb_gallery gallery_ids=&#8221;7996&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221; custom_padding=&#8221;||35px||false|false&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]We can see that all 50 users were active running the scenario after one or two seconds and were finishing the activity after 20 seconds.[\/et_pb_text][et_pb_gallery gallery_ids=&#8221;7998&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221; custom_padding=&#8221;||35px||false|false&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>In the above chart, we see the percentages of response times, distributed in time ranges in milliseconds.<\/p>\n<p>For instance, we can see that 17% of the requests took around 265 ms.<\/p>\n<p>[\/et_pb_text][et_pb_gallery gallery_ids=&#8221;8000&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221; custom_padding=&#8221;||35px||false|false&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>At a certain point in the above chart, we can see the percentages of the running requests and their response time in ms. We can zoom in and out the time interval.<\/p>\n<p>[\/et_pb_text][et_pb_gallery gallery_ids=&#8221;8002&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221; custom_padding=&#8221;||35px||false|false&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]Maximum 40 requests per second were running by 50 parallel users over 24 seconds with certain spikes of 25 req\/sec here and there. You can modify the time interval from the bottom of the chart.[\/et_pb_text][et_pb_gallery gallery_ids=&#8221;8004&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221; custom_padding=&#8221;||35px||false|false&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]50 users ramped up in 2 seconds executed the same scenario in 24 seconds. The number of finished responses over time was reported above. [\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||0px||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;2em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||10px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2>Conclusions<\/h2>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; hover_enabled=&#8221;0&#8243; border_color_left=&#8221;#ff6317&#8243; sticky_enabled=&#8221;0&#8243;]<\/p>\n<p>It was challenging to integrate and run performance tests into the CI\/CD pipeline on a regular basis. We talked about one way to do it, that worked for us. We\u2019ve touched a bit on the challenges we faced, the tools used, how to write the tests and how to prepare the data for them. We hope you enjoyed it!<br \/> Should you have any questions, don&#8217;t hesitate to <a href=\"https:\/\/www.berg-software.com\/en\/contact-berg-software\/\">contact us<\/a>.<\/p>\n<p>***<\/p>\n<p>How do <strong>you<\/strong>\u00a0do it? <a href=\"https:\/\/berg-software.com\/contact-berg-software\/\">Care to share your solution?<\/a><\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.4.1&#8243; custom_padding=&#8221;|||0px||&#8221; locked=&#8221;off&#8221;][et_pb_row use_custom_gutter=&#8221;on&#8221; gutter_width=&#8221;3&#8243; admin_label=&#8221;\uff3f&#8221; _builder_version=&#8221;4.4.6&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;4vh||8vh||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.6&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2>\uff3f<\/h2>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;3.22&#8243; background_color=&#8221;#eeeeee&#8221; custom_padding=&#8221;50px||50px||false|false&#8221; border_color_top=&#8221;#ff6317&#8243; global_module=&#8221;1642&#8243;][et_pb_row column_structure=&#8221;1_3,1_3,1_3&#8243; _builder_version=&#8221;4.4.1&#8243; custom_padding=&#8221;0px|||||&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;1_3&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_social_media_follow _builder_version=&#8221;4.4.4&#8243; text_orientation=&#8221;left&#8221;][et_pb_social_media_follow_network social_network=&#8221;linkedin&#8221; url=&#8221;https:\/\/www.linkedin.com\/company\/berg-computers-srl\/&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#007bb6&#8243; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]linkedin[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8221;twitter&#8221; url=&#8221;https:\/\/twitter.com\/berg_software&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#00aced&#8221; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]twitter[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8221;facebook&#8221; url=&#8221;https:\/\/www.facebook.com\/bergCOMPUTERS&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#3b5998&#8243; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]facebook[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8221;instagram&#8221; url=&#8221;https:\/\/www.instagram.com\/berg_software\/&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#ea2c59&#8243; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]instagram[\/et_pb_social_media_follow_network][\/et_pb_social_media_follow][\/et_pb_column][et_pb_column type=&#8221;1_3&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_post_nav in_same_term=&#8221;on&#8221; show_next=&#8221;off&#8221; _builder_version=&#8221;4.4.1&#8243; title_text_color=&#8221;#ff6317&#8243; custom_padding=&#8221;|25px|||false|false&#8221;][\/et_pb_post_nav][\/et_pb_column][et_pb_column type=&#8221;1_3&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_post_nav in_same_term=&#8221;on&#8221; show_prev=&#8221;off&#8221; _builder_version=&#8221;4.4.1&#8243; title_text_color=&#8221;#ff6317&#8243; custom_padding=&#8221;|||25px|false|false&#8221;][\/et_pb_post_nav][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; admin_label=&#8221;CONTACT&#8221; _builder_version=&#8221;4.4.1&#8243; background_color=&#8221;#d2d2d2&#8243; custom_padding=&#8221;75px||75px||false|false&#8221;][et_pb_row column_structure=&#8221;1_4,3_4&#8243; admin_label=&#8221;Service Section Title&#8221; _builder_version=&#8221;4.4.1&#8243; custom_padding=&#8221;||25px||false|false&#8221; animation_direction=&#8221;top&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;1_4&#8243; _builder_version=&#8221;3.25&#8243; custom_padding=&#8221;|||&#8221; custom_padding__hover=&#8221;|||&#8221;][\/et_pb_column][et_pb_column type=&#8221;3_4&#8243; _builder_version=&#8221;3.25&#8243; custom_padding=&#8221;|||&#8221; custom_padding__hover=&#8221;|||&#8221;][et_pb_text _builder_version=&#8221;4.4.1&#8243; text_font=&#8221;|300|||||||&#8221; text_text_color=&#8221;#ffffff&#8221; text_line_height=&#8221;1.1em&#8221; header_5_font=&#8221;|600|||||||&#8221; header_5_text_color=&#8221;#ffffff&#8221; header_5_font_size=&#8221;14px&#8221; header_5_line_height=&#8221;1.5em&#8221; custom_margin=&#8221;||||false|false&#8221;]29 years in business | 2700 software projects | 760 clients | 24 countries<\/p>\n<h5>We turn ideas into software. What is yours?<\/h5>\n<p>[\/et_pb_text][et_pb_text admin_label=&#8221;Title&#8221; _builder_version=&#8221;4.4.6&#8243; header_text_align=&#8221;center&#8221; header_2_font=&#8221;|300|||||||&#8221; header_2_text_align=&#8221;left&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;50px&#8221; header_2_line_height=&#8221;0.9em&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;25px||25px||false|false&#8221;]<\/p>\n<h2 id=\"Getintouch\">Get in touch<\/h2>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row column_structure=&#8221;1_4,3_4&#8243; _builder_version=&#8221;4.4.4&#8243;][et_pb_column type=&#8221;1_4&#8243; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_column][et_pb_column type=&#8221;3_4&#8243; _builder_version=&#8221;4.4.4&#8243;][et_pb_contact_form email=&#8221;contact@bergsoftprod.wpengine.com&#8221; custom_message=&#8221;WEBFORM MESSAGE||et_pb_line_break_holder||\uff3f||et_pb_line_break_holder||FROM: %%Name%%||et_pb_line_break_holder||EMAIL: %%Email%%||et_pb_line_break_holder||PHONE NUMBER: %%Phone_number%%||et_pb_line_break_holder||COMPANY: %%Company_name%%||et_pb_line_break_holder||TERMS &#038; CONDITIONS: %%Terms_and_Conditions%%||et_pb_line_break_holder||DATA PRIVACY POLICY: %%Data_Privacy_Policy%%||et_pb_line_break_holder||\uff3f||et_pb_line_break_holder||MESSAGE:||et_pb_line_break_holder||%%Message%%&#8221; success_message=&#8221;Thank you for reaching out! Your message was sent. We will get back to you right away.&#8221; _builder_version=&#8221;4.7.7&#8243; form_field_background_color=&#8221;#d2d2d2&#8243; form_field_text_color=&#8221;#ffffff&#8221; form_field_focus_background_color=&#8221;#ffffff&#8221; form_field_focus_text_color=&#8221;#000000&#8243; title_level=&#8221;h2&#8243; title_font=&#8221;|300|||||||&#8221; title_text_color=&#8221;#ff6317&#8243; title_font_size=&#8221;30px&#8221; form_field_line_height=&#8221;1.5em&#8221; custom_button=&#8221;on&#8221; button_text_size=&#8221;14px&#8221; button_text_color=&#8221;#ffffff&#8221; button_bg_color=&#8221;#ff6317&#8243; button_border_width=&#8221;0px&#8221; button_border_radius=&#8221;0px&#8221; button_icon=&#8221;%%3%%&#8221; button_on_hover=&#8221;off&#8221; border_color_all=&#8221;#ffffff&#8221; border_width_bottom=&#8221;1px&#8221;][et_pb_contact_field field_id=&#8221;Name&#8221; field_title=&#8221;Name *&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243; form_field_background_color=&#8221;#d2d2d2&#8243; form_field_text_color=&#8221;#ffffff&#8221; form_field_focus_background_color=&#8221;#ffffff&#8221; form_field_focus_text_color=&#8221;#000000&#8243; border_width_bottom=&#8221;1px&#8221; button_text_size__hover_enabled=&#8221;off&#8221; button_one_text_size__hover_enabled=&#8221;off&#8221; button_two_text_size__hover_enabled=&#8221;off&#8221; button_text_color__hover_enabled=&#8221;off&#8221; button_one_text_color__hover_enabled=&#8221;off&#8221; button_two_text_color__hover_enabled=&#8221;off&#8221; button_border_width__hover_enabled=&#8221;off&#8221; button_one_border_width__hover_enabled=&#8221;off&#8221; button_two_border_width__hover_enabled=&#8221;off&#8221; button_border_color__hover_enabled=&#8221;off&#8221; button_one_border_color__hover_enabled=&#8221;off&#8221; button_two_border_color__hover_enabled=&#8221;off&#8221; button_border_radius__hover_enabled=&#8221;off&#8221; button_one_border_radius__hover_enabled=&#8221;off&#8221; button_two_border_radius__hover_enabled=&#8221;off&#8221; button_letter_spacing__hover_enabled=&#8221;off&#8221; button_one_letter_spacing__hover_enabled=&#8221;off&#8221; button_two_letter_spacing__hover_enabled=&#8221;off&#8221; button_bg_color__hover_enabled=&#8221;off&#8221; button_one_bg_color__hover_enabled=&#8221;off&#8221; button_two_bg_color__hover_enabled=&#8221;off&#8221;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Email&#8221; field_title=&#8221;Email address *&#8221; field_type=&#8221;email&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243; button_text_size__hover_enabled=&#8221;off&#8221; button_one_text_size__hover_enabled=&#8221;off&#8221; button_two_text_size__hover_enabled=&#8221;off&#8221; button_text_color__hover_enabled=&#8221;off&#8221; button_one_text_color__hover_enabled=&#8221;off&#8221; button_two_text_color__hover_enabled=&#8221;off&#8221; button_border_width__hover_enabled=&#8221;off&#8221; button_one_border_width__hover_enabled=&#8221;off&#8221; button_two_border_width__hover_enabled=&#8221;off&#8221; button_border_color__hover_enabled=&#8221;off&#8221; button_one_border_color__hover_enabled=&#8221;off&#8221; button_two_border_color__hover_enabled=&#8221;off&#8221; button_border_radius__hover_enabled=&#8221;off&#8221; button_one_border_radius__hover_enabled=&#8221;off&#8221; button_two_border_radius__hover_enabled=&#8221;off&#8221; button_letter_spacing__hover_enabled=&#8221;off&#8221; button_one_letter_spacing__hover_enabled=&#8221;off&#8221; button_two_letter_spacing__hover_enabled=&#8221;off&#8221; button_bg_color__hover_enabled=&#8221;off&#8221; button_one_bg_color__hover_enabled=&#8221;off&#8221; button_two_bg_color__hover_enabled=&#8221;off&#8221;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Phone_number&#8221; field_title=&#8221;Phone number&#8221; required_mark=&#8221;off&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Company_name&#8221; field_title=&#8221;Company name&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Message&#8221; field_title=&#8221;Message *&#8221; field_type=&#8221;text&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243; form_field_background_color=&#8221;#d2d2d2&#8243; form_field_focus_background_color=&#8221;#ffffff&#8221; form_field_focus_text_color=&#8221;#000000&#8243; border_width_bottom=&#8221;1px&#8221; button_text_size__hover_enabled=&#8221;off&#8221; button_one_text_size__hover_enabled=&#8221;off&#8221; button_two_text_size__hover_enabled=&#8221;off&#8221; button_text_color__hover_enabled=&#8221;off&#8221; button_one_text_color__hover_enabled=&#8221;off&#8221; button_two_text_color__hover_enabled=&#8221;off&#8221; button_border_width__hover_enabled=&#8221;off&#8221; button_one_border_width__hover_enabled=&#8221;off&#8221; button_two_border_width__hover_enabled=&#8221;off&#8221; button_border_color__hover_enabled=&#8221;off&#8221; button_one_border_color__hover_enabled=&#8221;off&#8221; button_two_border_color__hover_enabled=&#8221;off&#8221; button_border_radius__hover_enabled=&#8221;off&#8221; button_one_border_radius__hover_enabled=&#8221;off&#8221; button_two_border_radius__hover_enabled=&#8221;off&#8221; button_letter_spacing__hover_enabled=&#8221;off&#8221; button_one_letter_spacing__hover_enabled=&#8221;off&#8221; button_two_letter_spacing__hover_enabled=&#8221;off&#8221; button_bg_color__hover_enabled=&#8221;off&#8221; button_one_bg_color__hover_enabled=&#8221;off&#8221; button_two_bg_color__hover_enabled=&#8221;off&#8221;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Terms_and_Conditions&#8221; field_title=&#8221; &#8221; field_type=&#8221;checkbox&#8221; checkbox_options=&#8221;%91{%22value%22:%22I have read and accepted the Terms and Conditions%22,%22checked%22:0,%22dragID%22:-1}%93&#8243; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Data_Privacy_Policy&#8221; field_title=&#8221; &#8221; field_type=&#8221;checkbox&#8221; checkbox_options=&#8221;%91{%22value%22:%22I have read and accepted the Data Privacy Policy%22,%22checked%22:0,%22dragID%22:-1}%93&#8243; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][\/et_pb_contact_form][\/et_pb_column][\/et_pb_row][\/et_pb_section]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When continuous development and delivery of features are performed at very high rates, the system performance must stay within defined constraints. Here&#8217;s how we developed and integrated Gatling performance tests into GitLab CI\/CD pipeline.<\/p>\n","protected":false},"author":12,"featured_media":6306,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"on","_et_pb_old_content":"","_et_gb_content_width":"2880","footnotes":""},"categories":[138,33],"tags":[],"class_list":["post-7967","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to","category-insights"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v16.1.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Performance tests &amp; integration into GitLab CI\/CD pipeline (w\/ Gatling)<\/title>\n<meta name=\"description\" content=\"We developed and integrated Gatling performance tests into GitLab CI\/CD pipeline. When continuous development and delivery of features\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Performance tests &amp; integration into GitLab CI\/CD pipeline (w\/ Gatling)\" \/>\n<meta property=\"og:description\" content=\"We developed and integrated Gatling performance tests into GitLab CI\/CD pipeline. When continuous development and delivery of features\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/\" \/>\n<meta property=\"og:site_name\" content=\"Berg Software\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/bergCOMPUTERS\/\" \/>\n<meta property=\"article:published_time\" content=\"2021-09-22T04:59:59+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-07-12T13:07:41+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.berg-software.com\/wp-content\/uploads\/Berg-Software-End-to-end-tests-an-GitLab-integration-00-Cover.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"600\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@berg_software\" \/>\n<meta name=\"twitter:site\" content=\"@berg_software\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"25 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#organization\",\"name\":\"Berg Software\",\"url\":\"https:\/\/www.berg-software.com\/en\/\",\"sameAs\":[\"https:\/\/www.facebook.com\/bergCOMPUTERS\/\",\"https:\/\/www.instagram.com\/berg_software\/\",\"https:\/\/www.linkedin.com\/company\/berg-computers-srl\/\",\"https:\/\/www.youtube.com\/channel\/UCw1FfcRJnC-CoKPwlcM10Iw\",\"https:\/\/twitter.com\/berg_software\"],\"logo\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#logo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/berg-software.com\/wp-content\/uploads\/berg-software-logo.png\",\"contentUrl\":\"https:\/\/berg-software.com\/wp-content\/uploads\/berg-software-logo.png\",\"width\":512,\"height\":512,\"caption\":\"Berg Software\"},\"image\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#logo\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#website\",\"url\":\"https:\/\/www.berg-software.com\/en\/\",\"name\":\"Berg Software\",\"description\":\"We turn ideas into software.\",\"publisher\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/www.berg-software.com\/en\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/www.berg-software.com\/wp-content\/uploads\/Berg-Software-End-to-end-tests-an-GitLab-integration-00-Cover.jpg\",\"contentUrl\":\"https:\/\/www.berg-software.com\/wp-content\/uploads\/Berg-Software-End-to-end-tests-an-GitLab-integration-00-Cover.jpg\",\"width\":1200,\"height\":600,\"caption\":\"Berg Software - End-to-end tests an GitLab integration - 00 Cover\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/#webpage\",\"url\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/\",\"name\":\"Performance tests & integration into GitLab CI\/CD pipeline (w\/ Gatling)\",\"isPartOf\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/#primaryimage\"},\"datePublished\":\"2021-09-22T04:59:59+00:00\",\"dateModified\":\"2022-07-12T13:07:41+00:00\",\"description\":\"We developed and integrated Gatling performance tests into GitLab CI\/CD pipeline. When continuous development and delivery of features\",\"breadcrumb\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/\",\"url\":\"https:\/\/www.berg-software.com\/en\/\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"position\":2,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/category\/insights\/\",\"url\":\"https:\/\/www.berg-software.com\/en\/category\/insights\/\",\"name\":\"Insights\"}},{\"@type\":\"ListItem\",\"position\":3,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/\",\"url\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/\",\"name\":\"Performance tests &#038; integration into GitLab CI\/CD pipeline (w\/ Gatling)\"}}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/#webpage\"},\"author\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#\/schema\/person\/4becfb1c9de08963757e6dc8531fef1a\"},\"headline\":\"Performance tests &#038; integration into GitLab CI\/CD pipeline (w\/ Gatling)\",\"datePublished\":\"2021-09-22T04:59:59+00:00\",\"dateModified\":\"2022-07-12T13:07:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/gaitling-performance-tests-integration-gitlab-ci-cd-pipeline\/#primaryimage\"},\"articleSection\":\"How to,Insights\",\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#\/schema\/person\/4becfb1c9de08963757e6dc8531fef1a\",\"name\":\"Ionu\\u021b Bucurescu\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","_links":{"self":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/posts\/7967","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/comments?post=7967"}],"version-history":[{"count":0,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/posts\/7967\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/media\/6306"}],"wp:attachment":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/media?parent=7967"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/categories?post=7967"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/tags?post=7967"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}