diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3d058fb2d995ec0903167c72a50be73d35d54baf..77a745cd5573698ae55228880abc06f1c929f777 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,6 +3,7 @@ variables:
   DOCKER_BUILDER_TAG: "$CI_COMMIT_SHA"
   DOCKER_DIND_TAG: "$CI_COMMIT_SHA"
   IMAGE_REMOVER_TAG: "$CI_COMMIT_SHA"
+  TOX_IMAGE_TAG: "$CI_COMMIT_SHA"
 
 stages:
   - validation
@@ -151,6 +152,16 @@ build_benchmark_test_runner_image:
       exists:
         - Dockerfile.benchmark-test-runner
 
+build_tox_test_runner_image:
+  extends: .build_docker_image
+  stage: build
+  variables:
+    BUILD_TARGET: "tox-test-runner"
+  rules:
+    - if: $CI_COMMIT_BRANCH
+      exists:
+        - Dockerfile.tox-test-runner
+
 prepare_example_hived_data_5m_image:
   extends: .prepare_hived_data_5m_image
   stage: example-build
@@ -191,7 +202,6 @@ example_jmeter_benchmark_job:
       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
@@ -203,6 +213,22 @@ example_jmeter_benchmark_job:
   tags:
     - public-runner-docker
 
+example_tox_test_job:
+  extends: .tox_test_job
+  stage: example-test
+  script:
+    - |
+      git clone https://github.com/pypa/sampleproject.git
+      cd sampleproject
+      sed -i s/py\{37,38,39,310\}/py311/ tox.ini
+      tox --result-json tox-result.json
+  artifacts:
+    paths:
+      - sampleproject/tox-result.json
+  when: manual
+  tags:
+    - public-runner-docker
+
 example_hived_data_image_cleanup:
   extends: .docker_image_cleanup_job
   stage: example-cleanup
diff --git a/Dockerfile.tox-test-runner b/Dockerfile.tox-test-runner
new file mode 100644
index 0000000000000000000000000000000000000000..69335b4f02ce2d88c1215b77ee4fd595c97eddcd
--- /dev/null
+++ b/Dockerfile.tox-test-runner
@@ -0,0 +1,12 @@
+# syntax=docker/dockerfile:1.4
+FROM python:3.11.0-alpine3.17
+
+RUN <<-EOF 
+  # Install system dependencies
+  apk add --no-cache bash git curl
+
+  # Install Python dependencies
+  pip3 install tox
+EOF
+
+CMD ["/bin/bash"]
\ No newline at end of file
diff --git a/docker-bake.hcl b/docker-bake.hcl
index 3370cb666a71a1c418ef9515f6d1feacafd94b4a..9fe70bc49fe7ebd2d516cb27a7ed971516392f73 100644
--- a/docker-bake.hcl
+++ b/docker-bake.hcl
@@ -35,4 +35,9 @@ target "docker-dind" {
 target "image-remover" {
   dockerfile = "Dockerfile.image-remover"
   tags = generate-tags("image-remover")
+}
+
+target "tox-test-runner" {
+  dockerfile = "Dockerfile.tox-test-runner"
+  tags = generate-tags("tox-test-runner")
 }
\ No newline at end of file
diff --git a/templates/test_jobs.gitlab-ci.yml b/templates/test_jobs.gitlab-ci.yml
index ab963dab36fbe99792afbd46e5724039ca44f151..49fadba5900798e2d764390a8e36dea034e3877f 100644
--- a/templates/test_jobs.gitlab-ci.yml
+++ b/templates/test_jobs.gitlab-ci.yml
@@ -1,8 +1,15 @@
 variables:
   BENCHMARK_IMAGE_TAG: "latest"
+  TOX_IMAGE_TAG: "latest"
+
+.artifact_config:
+  artifacts:
+    when: always
+    expire_in: 6 hours
 
 .jmeter_benchmark_job:
   image: registry.gitlab.syncad.com/hive/common-ci-configuration/benchmark-test-runner:${BENCHMARK_IMAGE_TAG}
+  artifacts: !reference [.artifact_config, artifacts]
 
 .jmeter_benchmark_with_haf_job:
   extends: .jmeter_benchmark_job
@@ -14,3 +21,20 @@ variables:
         PG_ACCESS: "host    haf_block_log    haf_app_admin    0.0.0.0/0    trust"
     - name: $APP_IMAGE
       alias: app
+
+.tox_test_job:
+  image: registry.gitlab.syncad.com/hive/common-ci-configuration/tox-test-runner:${TOX_IMAGE_TAG}
+  artifacts: !reference [.artifact_config, artifacts]
+
+.pattern_tests:
+  extends: .tox_test_job
+  variables:
+    ENDPOINT: app:$APP_PORT
+  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"
+    - name: $APP_IMAGE
+      alias: app