diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3031f74f8239dc50c959219c4965cffe95115fa5..3d058fb2d995ec0903167c72a50be73d35d54baf 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,5 @@ variables: + BENCHMARK_IMAGE_TAG: "$CI_COMMIT_SHA" DOCKER_BUILDER_TAG: "$CI_COMMIT_SHA" DOCKER_DIND_TAG: "$CI_COMMIT_SHA" IMAGE_REMOVER_TAG: "$CI_COMMIT_SHA" @@ -8,11 +9,13 @@ stages: - pre-build - build - example-build + - example-test - example-cleanup include: - template: Workflows/Branch-Pipelines.gitlab-ci.yml - local: templates/data_image_jobs.gitlab-ci.yml + - local: templates/test_jobs.gitlab-ci.yml .validation_job: stage: validation @@ -180,6 +183,26 @@ prepare_example_haf_data_5m_image: tags: - public-runner-docker +example_jmeter_benchmark_job: + extends: .jmeter_benchmark_job + stage: example-test + script: + - | + jmeter -n -t misc/example-jmeter-test.jmx -l jmeter_report.jtl -e -o web_jmeter_report + m2u --input jmeter_report.xml --output jmeter_junit_report.xml + artifacts: + expire_in: "30 days" + paths: + - web_jmeter_report/**/* + - jmeter.log + - jmeter_report.jtl + - jmeter_report.xml + reports: + junit: jmeter_junit_report.xml + when: manual + tags: + - public-runner-docker + example_hived_data_image_cleanup: extends: .docker_image_cleanup_job stage: example-cleanup @@ -204,4 +227,4 @@ example_haf_data_image_cleanup: - prepare_example_haf_data_5m_image when: manual tags: - - public-runner-docker \ No newline at end of file + - public-runner-docker diff --git a/misc/example-jmeter-test.jmx b/misc/example-jmeter-test.jmx new file mode 100644 index 0000000000000000000000000000000000000000..f4e8f6ca0485c34a58ee7a07f981aabb9d937302 --- /dev/null +++ b/misc/example-jmeter-test.jmx @@ -0,0 +1,194 @@ +<?xml version="1.0" encoding="UTF-8"?> +<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.3"> + <hashTree> + <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="build-web-test-plan" enabled="true"> + <stringProp name="TestPlan.comments"></stringProp> + <boolProp name="TestPlan.functional_mode">false</boolProp> + <boolProp name="TestPlan.serialize_threadgroups">false</boolProp> + <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="TestPlan.user_define_classpath"></stringProp> + </TestPlan> + <hashTree> + <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Example test scenario" enabled="true"> + <stringProp name="ThreadGroup.on_sample_error">continue</stringProp> + <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> + <boolProp name="LoopController.continue_forever">false</boolProp> + <intProp name="LoopController.loops">-1</intProp> + </elementProp> + <stringProp name="ThreadGroup.num_threads">5</stringProp> + <stringProp name="ThreadGroup.ramp_time">5</stringProp> + <longProp name="ThreadGroup.start_time">1373789594000</longProp> + <longProp name="ThreadGroup.end_time">1373789594000</longProp> + <boolProp name="ThreadGroup.scheduler">true</boolProp> + <stringProp name="ThreadGroup.duration">60</stringProp> + <stringProp name="ThreadGroup.delay">5</stringProp> + <stringProp name="TestPlan.comments">Virtual Users Running Example test scenario. +Make test last 1 minute (see Scheduler)</stringProp> + <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp> + </ThreadGroup> + <hashTree> + <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain">example.org</stringProp> + <stringProp name="HTTPSampler.port"></stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> + <stringProp name="HTTPSampler.path"></stringProp> + <stringProp name="TestPlan.comments">Notice Timeouts: +Read to 30s +Connect to 5s</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> + <stringProp name="HTTPSampler.connect_timeout">5000</stringProp> + <stringProp name="HTTPSampler.response_timeout">30000</stringProp> + </ConfigTestElement> + <hashTree/> + <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> + <collectionProp name="CookieManager.cookies"/> + <boolProp name="CookieManager.clearEachIteration">false</boolProp> + <boolProp name="CookieManager.controlledByThreadGroup">false</boolProp> + </CookieManager> + <hashTree/> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="User-Agent" elementType="Header"> + <stringProp name="Header.name">User-Agent</stringProp> + <stringProp name="Header.value"> Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:48.0) Gecko/20100101 Firefox/48.0</stringProp> + </elementProp> + <elementProp name="Accept" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value"> text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</stringProp> + </elementProp> + <elementProp name="Accept-Language" elementType="Header"> + <stringProp name="Header.name">Accept-Language</stringProp> + <stringProp name="Header.value"> fr,en-US;q=0.7,en;q=0.3</stringProp> + </elementProp> + <elementProp name="Accept-Encoding" elementType="Header"> + <stringProp name="Header.name">Accept-Encoding</stringProp> + <stringProp name="Header.value"> gzip, deflate</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Home Page" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables pré-définies" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"></stringProp> + <stringProp name="HTTPSampler.port"></stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> + <stringProp name="HTTPSampler.path">/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"></stringProp> + <stringProp name="HTTPSampler.connect_timeout"></stringProp> + <stringProp name="HTTPSampler.response_timeout"></stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-868354929"><h1>Example Domain</h1></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">16</intProp> + <stringProp name="Assertion.custom_message"></stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + <TestAction guiclass="TestActionGui" testclass="TestAction" testname="ThinkTime1s" enabled="true"> + <intProp name="ActionProcessor.action">1</intProp> + <intProp name="ActionProcessor.target">0</intProp> + <stringProp name="ActionProcessor.duration">0</stringProp> + </TestAction> + <hashTree> + <UniformRandomTimer guiclass="UniformRandomTimerGui" testclass="UniformRandomTimer" testname="URT" enabled="true"> + <stringProp name="ConstantTimer.delay">1000</stringProp> + <stringProp name="RandomTimer.range">100.0</stringProp> + </UniformRandomTimer> + <hashTree/> + </hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Page Returning 404" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="Variables pré-définies" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"></stringProp> + <stringProp name="HTTPSampler.port"></stringProp> + <stringProp name="HTTPSampler.protocol"></stringProp> + <stringProp name="HTTPSampler.contentEncoding"></stringProp> + <stringProp name="HTTPSampler.path">/test</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"></stringProp> + <stringProp name="HTTPSampler.connect_timeout"></stringProp> + <stringProp name="HTTPSampler.response_timeout"></stringProp> + <stringProp name="TestPlan.comments">It does not fails because we use an assertion that ignores status</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assertion_404" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="51512">404</stringProp> + </collectionProp> + <stringProp name="TestPlan.comments">The assertion is specia: +- It ignores status which would make it in error by default (404) +- It checks Response Code is equal to 404</stringProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">true</boolProp> + <intProp name="Assertion.test_type">8</intProp> + <stringProp name="Assertion.custom_message"></stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true"> + <boolProp name="ResultCollector.error_logging">false</boolProp> + <objProp> + <name>saveConfig</name> + <value class="SampleSaveConfiguration"> + <time>true</time> + <latency>true</latency> + <timestamp>true</timestamp> + <success>true</success> + <label>true</label> + <code>true</code> + <message>true</message> + <threadName>true</threadName> + <dataType>true</dataType> + <encoding>true</encoding> + <assertions>true</assertions> + <subresults>true</subresults> + <responseData>false</responseData> + <samplerData>false</samplerData> + <xml>true</xml> + <fieldNames>true</fieldNames> + <responseHeaders>true</responseHeaders> + <requestHeaders>true</requestHeaders> + <responseDataOnError>false</responseDataOnError> + <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage> + <assertionsResultsToSave>0</assertionsResultsToSave> + <bytes>true</bytes> + <sentBytes>true</sentBytes> + <url>true</url> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <idleTime>true</idleTime> + <connectTime>true</connectTime> + </value> + </objProp> + <stringProp name="TestPlan.comments">For scripting only</stringProp> + <stringProp name="filename">jmeter_report.xml</stringProp> + </ResultCollector> + <hashTree/> + </hashTree> + </hashTree> +</jmeterTestPlan> diff --git a/templates/test_jobs.gitlab-ci.yml b/templates/test_jobs.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..1f65ccf8ee342ad2e3bb3bb494a922600226cdc6 --- /dev/null +++ b/templates/test_jobs.gitlab-ci.yml @@ -0,0 +1,14 @@ +variables: + BENCHMARK_IMAGE_TAG: "latest" + +.jmeter_benchmark_job: + image: registry.gitlab.syncad.com/hive/common-ci-configuration/benchmark-test-runner:${BENCHMARK_IMAGE_TAG} + +.jmeter_benchmark_with_haf_job: + extends: .jmeter_benchmark_job + services: + - name: $HAF_IMAGE_NAME + alias: haf-instance + variables: + # Allow access from any network to eliminate CI IP addressing problems + PG_ACCESS: "host haf_block_log haf_app_admin 0.0.0.0/0 trust"