diff --git a/.drone.yml b/.drone.yml
index 57c888a7d9..93a471fae1 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -498,6 +498,75 @@ steps:
       - name: deps
         path: /go
 
+---
+kind: pipeline
+type: docker
+name: testing-e2e
+
+platform:
+  os: linux
+  arch: amd64
+
+depends_on:
+  - compliance
+
+trigger:
+  event:
+    - pull_request
+
+volumes:
+  - name: deps
+    temp: {}
+
+services:
+  - name: pgsql
+    pull: default
+    image: postgres:10
+    environment:
+      POSTGRES_DB: testgitea-e2e
+      POSTGRES_PASSWORD: postgres
+      POSTGRES_INITDB_ARGS: --encoding=UTF8 --lc-collate='en_US.UTF-8' --lc-ctype='en_US.UTF-8'
+
+steps:
+  - name: deps-frontend
+    image: node:16
+    pull: always
+    commands:
+      - make deps-frontend
+
+  - name: build-frontend
+    image: node:16
+    commands:
+      - make frontend
+    depends_on: [deps-frontend]
+
+  - name: deps-backend
+    image: golang:1.18
+    pull: always
+    commands:
+      - make deps-backend
+    volumes:
+      - name: deps
+        path: /go
+
+  # TODO: We should probably build all dependencies into a test image
+  - name: test-e2e
+    image: mcr.microsoft.com/playwright:v1.23.1-focal
+    commands:
+      - curl -sLO https://go.dev/dl/go1.18.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.18.linux-amd64.tar.gz
+      - groupadd --gid 1001 gitea && useradd -m --gid 1001 --uid 1001 gitea
+      - apt-get -qq update && apt-get -qqy install build-essential
+      - export TEST_PGSQL_SCHEMA=''
+      - ./build/test-env-prepare.sh
+      - su gitea bash -c "export PATH=$PATH:/usr/local/go/bin && timeout -s ABRT 40m make test-e2e-pgsql"
+    environment:
+      GOPROXY: https://goproxy.io
+      GOSUMDB: sum.golang.org
+      USE_REPO_TEST_DIR: 1
+      TEST_PGSQL_DBNAME: 'testgitea-e2e'
+      DEBIAN_FRONTEND: noninteractive
+    depends_on: [build-frontend, deps-backend]
+
 ---
 kind: pipeline
 name: update_translations
diff --git a/.gitignore b/.gitignore
index eab92b49ad..0407dfbbd1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,21 +63,14 @@ cpu.out
 /indexers
 /log
 /public/img/avatar
-/integrations/gitea-integration-mysql
-/integrations/gitea-integration-mysql8
-/integrations/gitea-integration-pgsql
-/integrations/gitea-integration-sqlite
-/integrations/gitea-integration-mssql
-/integrations/indexers-mysql
-/integrations/indexers-mysql8
-/integrations/indexers-pgsql
-/integrations/indexers-sqlite
-/integrations/indexers-mssql
-/integrations/sqlite.ini
-/integrations/mysql.ini
-/integrations/mysql8.ini
-/integrations/pgsql.ini
-/integrations/mssql.ini
+/tests/integration/gitea-integration-*
+/tests/integration/indexers-*
+/tests/e2e/gitea-e2e-*
+/tests/e2e/indexers-*
+/tests/e2e/reports
+/tests/e2e/test-artifacts
+/tests/e2e/test-snapshots
+/tests/*.ini
 /node_modules
 /yarn.lock
 /yarn-error.log
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 61ab3de4b9..b13af805bc 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -86,8 +86,10 @@ Here's how to run the test suite:
 |                                        |                                                  |
 | :------------------------------------- | :----------------------------------------------- |
 |``make test[\#TestSpecificName]``       |  run unit test  |
-|``make test-sqlite[\#TestSpecificName]``|  run [integration](integrations) test for SQLite |
-|[More details about integrations](integrations/README.md)  |
+|``make test-sqlite[\#TestSpecificName]``|  run [integration](tests/integration) test for SQLite |
+|[More details about integration tests](tests/integration/README.md)  |
+|``make test-e2e-sqlite[\#TestSpecificFileName]``|  run [end-to-end](tests/e2e) test for SQLite |
+|[More details about e2e tests](tests/e2e/README.md)  |
 
 ## Vendoring
 
@@ -168,7 +170,7 @@ import (
 
 To maintain understandable code and avoid circular dependencies it is important to have a good structure of the code. The Gitea code is divided into the following parts:
 
-- **integration:** Integrations tests
+- **integration:** Integration tests
 - **models:** Contains the data structures used by xorm to construct database tables. It also contains supporting functions to query and update the database. Dependencies to other code in Gitea should be avoided although some modules might be needed (for example for logging).
 - **models/fixtures:** Sample model data used in integration tests.
 - **models/migrations:** Handling of database migrations between versions. PRs that changes a database structure shall also have a migration step.
diff --git a/Makefile b/Makefile
index 03b5bd5058..96d0b992ed 100644
--- a/Makefile
+++ b/Makefile
@@ -98,7 +98,7 @@ LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(G
 
 LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
 
-GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/models/migrations code.gitea.io/gitea/integrations/migration-test code.gitea.io/gitea/integrations,$(shell $(GO) list ./... | grep -v /vendor/))
+GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/models/migrations code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
 
 FOMANTIC_WORK_DIR := web_src/fomantic
 
@@ -122,7 +122,7 @@ TEST_TAGS ?= sqlite sqlite_unlock_notify
 
 TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMANTIC_WORK_DIR)/node_modules $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR)
 
-GO_DIRS := cmd integrations models modules routers build services tools
+GO_DIRS := cmd tests models modules routers build services tools
 
 GO_SOURCES := $(wildcard *.go)
 GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" -not -path modules/options/bindata.go -not -path modules/public/bindata.go -not -path modules/templates/bindata.go)
@@ -131,6 +131,11 @@ ifeq ($(filter $(TAGS_SPLIT),bindata),bindata)
 	GO_SOURCES += $(BINDATA_DEST)
 endif
 
+# Force installation of playwright dependencies by setting this flag
+ifdef DEPS_PLAYWRIGHT
+	PLAYWRIGHT_FLAGS += --with-deps
+endif
+
 SWAGGER_SPEC := templates/swagger/v1_json.tmpl
 SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|g
 SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|"basePath": "/api/v1"|g
@@ -182,6 +187,7 @@ help:
 	@echo " - test                             test everything"
 	@echo " - test-frontend                    test frontend files"
 	@echo " - test-backend                     test backend files"
+	@echo " - test-e2e[\#TestSpecificName]     test end to end using playwright"
 	@echo " - webpack                          build webpack files"
 	@echo " - svg                              build svg files"
 	@echo " - fomantic                         build fomantic files"
@@ -236,9 +242,13 @@ clean:
 	$(GO) clean -i ./...
 	rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) $(BINDATA_HASH) \
 		integrations*.test \
-		integrations/gitea-integration-pgsql/ integrations/gitea-integration-mysql/ integrations/gitea-integration-mysql8/ integrations/gitea-integration-sqlite/ \
-		integrations/gitea-integration-mssql/ integrations/indexers-mysql/ integrations/indexers-mysql8/ integrations/indexers-pgsql integrations/indexers-sqlite \
-		integrations/indexers-mssql integrations/mysql.ini integrations/mysql8.ini integrations/pgsql.ini integrations/mssql.ini man/
+		e2e*.test \
+		tests/integration/gitea-integration-pgsql/ tests/integration/gitea-integration-mysql/ tests/integration/gitea-integration-mysql8/ tests/integration/gitea-integration-sqlite/ \
+		tests/integration/gitea-integration-mssql/ tests/integration/indexers-mysql/ tests/integration/indexers-mysql8/ tests/integration/indexers-pgsql tests/integration/indexers-sqlite \
+		tests/integration/indexers-mssql tests/mysql.ini tests/mysql8.ini tests/pgsql.ini tests/mssql.ini man/ \
+		tests/e2e/gitea-e2e-pgsql/ tests/e2e/gitea-e2e-mysql/ tests/e2e/gitea-e2e-mysql8/ tests/e2e/gitea-e2e-sqlite/ \
+		tests/e2e/gitea-e2e-mssql/ tests/e2e/indexers-mysql/ tests/e2e/indexers-mysql8/ tests/e2e/indexers-pgsql/ tests/e2e/indexers-sqlite/ \
+		tests/e2e/indexers-mssql/ tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/
 
 .PHONY: fmt
 fmt:
@@ -318,7 +328,7 @@ lint: lint-frontend lint-backend
 
 .PHONY: lint-frontend
 lint-frontend: node_modules
-	npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js docs/assets/js
+	npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js docs/assets/js tests/e2e/*.test.e2e.js tests/e2e/utils_e2e.js
 	npx stylelint --color --max-warnings=0 web_src/less
 	npx spectral lint -q -F hint $(SWAGGER_SPEC)
 	npx markdownlint docs *.md
@@ -399,24 +409,26 @@ tidy-check: tidy
 
 generate-ini-sqlite:
 	sed -e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
-			integrations/sqlite.ini.tmpl > integrations/sqlite.ini
+		-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
+		-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
+			tests/sqlite.ini.tmpl > tests/sqlite.ini
 
 .PHONY: test-sqlite
 test-sqlite: integrations.sqlite.test generate-ini-sqlite
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test
 
 .PHONY: test-sqlite\#%
 test-sqlite\#%: integrations.sqlite.test generate-ini-sqlite
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test -test.run $(subst .,/,$*)
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test -test.run $(subst .,/,$*)
 
 .PHONY: test-sqlite-migration
 test-sqlite-migration:  migrations.sqlite.test migrations.individual.sqlite.test generate-ini-sqlite
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./migrations.sqlite.test
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./migrations.individual.sqlite.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./migrations.sqlite.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./migrations.individual.sqlite.test
 
 .PHONY: test-sqlite-migration\#%
 test-sqlite-migration\#%:  migrations.sqlite.test migrations.individual.sqlite.test generate-ini-sqlite
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./migrations.individual.sqlite.test -test.run $(subst .,/,$*)
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./migrations.individual.sqlite.test -test.run $(subst .,/,$*)
 
 
 generate-ini-mysql:
@@ -425,20 +437,22 @@ generate-ini-mysql:
 		-e 's|{{TEST_MYSQL_USERNAME}}|${TEST_MYSQL_USERNAME}|g' \
 		-e 's|{{TEST_MYSQL_PASSWORD}}|${TEST_MYSQL_PASSWORD}|g' \
 		-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
-			integrations/mysql.ini.tmpl > integrations/mysql.ini
+		-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
+		-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
+			tests/mysql.ini.tmpl > tests/mysql.ini
 
 .PHONY: test-mysql
 test-mysql: integrations.mysql.test generate-ini-mysql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./integrations.mysql.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test
 
 .PHONY: test-mysql\#%
 test-mysql\#%: integrations.mysql.test generate-ini-mysql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./integrations.mysql.test -test.run $(subst .,/,$*)
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test -test.run $(subst .,/,$*)
 
 .PHONY: test-mysql-migration
 test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test generate-ini-mysql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./migrations.mysql.test
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./migrations.individual.mysql.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./migrations.mysql.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./migrations.individual.mysql.test
 
 generate-ini-mysql8:
 	sed -e 's|{{TEST_MYSQL8_HOST}}|${TEST_MYSQL8_HOST}|g' \
@@ -446,20 +460,22 @@ generate-ini-mysql8:
 		-e 's|{{TEST_MYSQL8_USERNAME}}|${TEST_MYSQL8_USERNAME}|g' \
 		-e 's|{{TEST_MYSQL8_PASSWORD}}|${TEST_MYSQL8_PASSWORD}|g' \
 		-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
-			integrations/mysql8.ini.tmpl > integrations/mysql8.ini
+		-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
+		-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
+			tests/mysql8.ini.tmpl > tests/mysql8.ini
 
 .PHONY: test-mysql8
 test-mysql8: integrations.mysql8.test generate-ini-mysql8
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql8.ini ./integrations.mysql8.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./integrations.mysql8.test
 
 .PHONY: test-mysql8\#%
 test-mysql8\#%: integrations.mysql8.test generate-ini-mysql8
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql8.ini ./integrations.mysql8.test -test.run $(subst .,/,$*)
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./integrations.mysql8.test -test.run $(subst .,/,$*)
 
 .PHONY: test-mysql8-migration
 test-mysql8-migration: migrations.mysql8.test migrations.individual.mysql8.test generate-ini-mysql8
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql8.ini ./migrations.mysql8.test
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql8.ini ./migrations.individual.mysql8.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./migrations.mysql8.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./migrations.individual.mysql8.test
 
 generate-ini-pgsql:
 	sed -e 's|{{TEST_PGSQL_HOST}}|${TEST_PGSQL_HOST}|g' \
@@ -468,20 +484,22 @@ generate-ini-pgsql:
 		-e 's|{{TEST_PGSQL_PASSWORD}}|${TEST_PGSQL_PASSWORD}|g' \
 		-e 's|{{TEST_PGSQL_SCHEMA}}|${TEST_PGSQL_SCHEMA}|g' \
 		-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
-			integrations/pgsql.ini.tmpl > integrations/pgsql.ini
+		-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
+		-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
+			tests/pgsql.ini.tmpl > tests/pgsql.ini
 
 .PHONY: test-pgsql
 test-pgsql: integrations.pgsql.test generate-ini-pgsql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/pgsql.ini ./integrations.pgsql.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test
 
 .PHONY: test-pgsql\#%
 test-pgsql\#%: integrations.pgsql.test generate-ini-pgsql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/pgsql.ini ./integrations.pgsql.test -test.run $(subst .,/,$*)
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.run $(subst .,/,$*)
 
 .PHONY: test-pgsql-migration
 test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test generate-ini-pgsql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/pgsql.ini ./migrations.pgsql.test
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/pgsql.ini ./migrations.individual.pgsql.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./migrations.pgsql.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./migrations.individual.pgsql.test
 
 generate-ini-mssql:
 	sed -e 's|{{TEST_MSSQL_HOST}}|${TEST_MSSQL_HOST}|g' \
@@ -489,85 +507,140 @@ generate-ini-mssql:
 		-e 's|{{TEST_MSSQL_USERNAME}}|${TEST_MSSQL_USERNAME}|g' \
 		-e 's|{{TEST_MSSQL_PASSWORD}}|${TEST_MSSQL_PASSWORD}|g' \
 		-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
-			integrations/mssql.ini.tmpl > integrations/mssql.ini
+		-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
+		-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
+			tests/mssql.ini.tmpl > tests/mssql.ini
 
 .PHONY: test-mssql
 test-mssql: integrations.mssql.test generate-ini-mssql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mssql.ini ./integrations.mssql.test
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test
 
 .PHONY: test-mssql\#%
 test-mssql\#%: integrations.mssql.test generate-ini-mssql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mssql.ini ./integrations.mssql.test -test.run $(subst .,/,$*)
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test -test.run $(subst .,/,$*)
 
 .PHONY: test-mssql-migration
 test-mssql-migration: migrations.mssql.test migrations.individual.mssql.test generate-ini-mssql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mssql.ini ./migrations.mssql.test -test.failfast
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mssql.ini ./migrations.individual.mssql.test -test.failfast
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./migrations.mssql.test -test.failfast
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./migrations.individual.mssql.test -test.failfast
+
+.PHONY: playwright
+playwright: $(PLAYWRIGHT_DIR)
+	npm install --no-save @playwright/test
+	npx playwright install $(PLAYWRIGHT_FLAGS)
+
+.PHONY: test-e2e%
+test-e2e%: TEST_TYPE ?= e2e
+	# Clear display env variable. Otherwise, chromium tests can fail.
+	DISPLAY=
+
+.PHONY: test-e2e
+test-e2e: test-e2e-sqlite
+
+.PHONY: test-e2e-sqlite
+test-e2e-sqlite: playwright e2e.sqlite.test generate-ini-sqlite
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test
+
+.PHONY: test-e2e-sqlite\#%
+test-e2e-sqlite\#%: playwright e2e.sqlite.test generate-ini-sqlite
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test -test.run TestE2e/$*
+
+.PHONY: test-e2e-mysql
+test-e2e-mysql: playwright e2e.mysql.test generate-ini-mysql
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./e2e.mysql.test
+
+.PHONY: test-e2e-mysql\#%
+test-e2e-mysql\#%: playwright e2e.mysql.test generate-ini-mysql
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./e2e.mysql.test -test.run TestE2e/$*
+
+.PHONY: test-e2e-mysql8
+test-e2e-mysql8: playwright e2e.mysql8.test generate-ini-mysql8
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./e2e.mysql8.test
+
+.PHONY: test-e2e-mysql8\#%
+test-e2e-mysql8\#%: playwright e2e.mysql8.test generate-ini-mysql8
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./e2e.mysql8.test -test.run TestE2e/$*
+
+.PHONY: test-e2e-pgsql
+test-e2e-pgsql: playwright e2e.pgsql.test generate-ini-pgsql
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./e2e.pgsql.test
+
+.PHONY: test-e2e-pgsql\#%
+test-e2e-pgsql\#%: playwright e2e.pgsql.test generate-ini-pgsql
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./e2e.pgsql.test -test.run TestE2e/$*
+
+.PHONY: test-e2e-mssql
+test-e2e-mssql: playwright e2e.mssql.test generate-ini-mssql
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./e2e.mssql.test
+
+.PHONY: test-e2e-mssql\#%
+test-e2e-mssql\#%: playwright e2e.mssql.test generate-ini-mssql
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./e2e.mssql.test -test.run TestE2e/$*
 
 .PHONY: bench-sqlite
 bench-sqlite: integrations.sqlite.test generate-ini-sqlite
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
 
 .PHONY: bench-mysql
 bench-mysql: integrations.mysql.test generate-ini-mysql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./integrations.mysql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
 
 .PHONY: bench-mssql
 bench-mssql: integrations.mssql.test generate-ini-mssql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mssql.ini ./integrations.mssql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
 
 .PHONY: bench-pgsql
 bench-pgsql: integrations.pgsql.test generate-ini-pgsql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/pgsql.ini ./integrations.pgsql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
 
 .PHONY: integration-test-coverage
 integration-test-coverage: integrations.cover.test generate-ini-mysql
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./integrations.cover.test -test.coverprofile=integration.coverage.out
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.cover.test -test.coverprofile=integration.coverage.out
 
 .PHONY: integration-test-coverage-sqlite
 integration-test-coverage-sqlite: integrations.cover.sqlite.test generate-ini-sqlite
-	GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./integrations.cover.sqlite.test -test.coverprofile=integration.coverage.out
+	GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.cover.sqlite.test -test.coverprofile=integration.coverage.out
 
 integrations.mysql.test: git-check $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -o integrations.mysql.test
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql.test
 
 integrations.mysql8.test: git-check $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -o integrations.mysql8.test
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql8.test
 
 integrations.pgsql.test: git-check $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -o integrations.pgsql.test
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.pgsql.test
 
 integrations.mssql.test: git-check $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -o integrations.mssql.test
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mssql.test
 
 integrations.sqlite.test: git-check $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -o integrations.sqlite.test -tags '$(TEST_TAGS)'
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.sqlite.test -tags '$(TEST_TAGS)'
 
 integrations.cover.test: git-check $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -coverpkg $(shell echo $(GO_PACKAGES) | tr ' ' ',') -o integrations.cover.test
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_PACKAGES) | tr ' ' ',') -o integrations.cover.test
 
 integrations.cover.sqlite.test: git-check $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -coverpkg $(shell echo $(GO_PACKAGES) | tr ' ' ',') -o integrations.cover.sqlite.test -tags '$(TEST_TAGS)'
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_PACKAGES) | tr ' ' ',') -o integrations.cover.sqlite.test -tags '$(TEST_TAGS)'
 
 .PHONY: migrations.mysql.test
 migrations.mysql.test: $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations/migration-test -o migrations.mysql.test
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql.test
 
 .PHONY: migrations.mysql8.test
 migrations.mysql8.test: $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations/migration-test -o migrations.mysql8.test
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql8.test
 
 .PHONY: migrations.pgsql.test
 migrations.pgsql.test: $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations/migration-test -o migrations.pgsql.test
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.pgsql.test
 
 .PHONY: migrations.mssql.test
 migrations.mssql.test: $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations/migration-test -o migrations.mssql.test
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mssql.test
 
 .PHONY: migrations.sqlite.test
 migrations.sqlite.test: $(GO_SOURCES)
-	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations/migration-test -o migrations.sqlite.test -tags '$(TEST_TAGS)'
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.sqlite.test -tags '$(TEST_TAGS)'
 
 .PHONY: migrations.individual.mysql.test
 migrations.individual.mysql.test: $(GO_SOURCES)
@@ -589,6 +662,21 @@ migrations.individual.mssql.test: $(GO_SOURCES)
 migrations.individual.sqlite.test: $(GO_SOURCES)
 	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/models/migrations -o migrations.individual.sqlite.test -tags '$(TEST_TAGS)'
 
+e2e.mysql.test: $(GO_SOURCES)
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql.test
+
+e2e.mysql8.test: $(GO_SOURCES)
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql8.test
+
+e2e.pgsql.test: $(GO_SOURCES)
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.pgsql.test
+
+e2e.mssql.test: $(GO_SOURCES)
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mssql.test
+
+e2e.sqlite.test: $(GO_SOURCES)
+	$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.sqlite.test -tags '$(TEST_TAGS)'
+
 .PHONY: check
 check: test
 
diff --git a/build/code-batch-process.go b/build/code-batch-process.go
index 0f8dbd40fe..24b13470ab 100644
--- a/build/code-batch-process.go
+++ b/build/code-batch-process.go
@@ -61,7 +61,7 @@ func newFileCollector(fileFilter string, batchSize int) (*fileCollector, error)
 			"build",
 			"cmd",
 			"contrib",
-			"integrations",
+			"tests",
 			"models",
 			"modules",
 			"routers",
@@ -71,8 +71,8 @@ func newFileCollector(fileFilter string, batchSize int) (*fileCollector, error)
 		co.includePatterns = append(co.includePatterns, regexp.MustCompile(`.*\.go$`))
 
 		co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`.*\bbindata\.go$`))
-		co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`integrations/gitea-repositories-meta`))
-		co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`integrations/migration-test`))
+		co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/gitea-repositories-meta`))
+		co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/integration/migration-test`))
 		co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`modules/git/tests`))
 		co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`models/fixtures`))
 		co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`models/migrations/fixtures`))
diff --git a/contrib/pr/checkout.go b/contrib/pr/checkout.go
index 900b44d167..85476afd01 100644
--- a/contrib/pr/checkout.go
+++ b/contrib/pr/checkout.go
@@ -112,7 +112,7 @@ func runPR() {
 	unittest.LoadFixtures()
 	util.RemoveAll(setting.RepoRootPath)
 	util.RemoveAll(repo_module.LocalCopyPath())
-	unittest.CopyDir(path.Join(curDir, "integrations/gitea-repositories-meta"), setting.RepoRootPath)
+	unittest.CopyDir(path.Join(curDir, "tests/gitea-repositories-meta"), setting.RepoRootPath)
 
 	log.Printf("[PR] Setting up router\n")
 	// routers.GlobalInit()
diff --git a/docs/content/doc/developers/guidelines-backend.md b/docs/content/doc/developers/guidelines-backend.md
index 4280aa80fb..b680d73c82 100644
--- a/docs/content/doc/developers/guidelines-backend.md
+++ b/docs/content/doc/developers/guidelines-backend.md
@@ -33,7 +33,9 @@ To maintain understandable code and avoid circular dependencies it is important
 
 - `build`: Scripts to help build Gitea.
 - `cmd`: All Gitea actual sub commands includes web, doctor, serv, hooks, admin and etc. `web` will start the web service. `serv` and `hooks` will be invoked by Git or OpenSSH. Other sub commands could help to maintain Gitea.
-- `integrations`: Integration tests
+- `tests`: Common test utility functions
+  - `tests/integration`: Integration tests, to test back-end regressions
+  - `tests/e2e`: E2e tests, to test test front-end <> back-end compatibility and visual regressions.
 - `models`: Contains the data structures used by xorm to construct database tables. It also contains functions to query and update the database. Dependencies to other Gitea code should be avoided. You can make exceptions in cases such as logging.
   - `models/db`: Basic database operations. All other `models/xxx` packages should depend on this package. The `GetEngine` function should only be invoked from `models/`.
   - `models/fixtures`: Sample data used in unit tests and integration tests. One `yml` file means one table which will be loaded into database when beginning the tests.
diff --git a/docs/content/doc/developers/hacking-on-gitea.en-us.md b/docs/content/doc/developers/hacking-on-gitea.en-us.md
index abefb1ca96..361ab530fa 100644
--- a/docs/content/doc/developers/hacking-on-gitea.en-us.md
+++ b/docs/content/doc/developers/hacking-on-gitea.en-us.md
@@ -309,7 +309,7 @@ will run the integration tests in an SQLite environment. Integration tests
 require `git lfs` to be installed. Other database tests are available but
 may need adjustment to the local environment.
 
-Take a look at [`integrations/README.md`](https://github.com/go-gitea/gitea/blob/main/integrations/README.md)
+Take a look at [`tests/integration/README.md`](https://github.com/go-gitea/gitea/blob/main/tests/integration/README.md)
 for more information and how to run a single test.
 
 ### Testing for a PR
diff --git a/models/migrations/migrations_test.go b/models/migrations/migrations_test.go
index 53e4f35395..5cd70626b4 100644
--- a/models/migrations/migrations_test.go
+++ b/models/migrations/migrations_test.go
@@ -46,7 +46,7 @@ func TestMain(m *testing.M) {
 
 	giteaConf := os.Getenv("GITEA_CONF")
 	if giteaConf == "" {
-		giteaConf = path.Join(filepath.Dir(setting.AppPath), "integrations/sqlite.ini")
+		giteaConf = path.Join(filepath.Dir(setting.AppPath), "tests/sqlite.ini")
 		fmt.Printf("Environment variable $GITEA_CONF not set - defaulting to %s\n", giteaConf)
 	}
 
@@ -205,7 +205,7 @@ func prepareTestEnv(t *testing.T, skip int, syncModels ...interface{}) (*xorm.En
 	ourSkip += skip
 	deferFn := PrintCurrentTest(t, ourSkip)
 	assert.NoError(t, os.RemoveAll(setting.RepoRootPath))
-	assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath))
+	assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath))
 	ownerDirs, err := os.ReadDir(setting.RepoRootPath)
 	if err != nil {
 		assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
diff --git a/models/migrations/testlogger_test.go b/models/migrations/testlogger_test.go
index adbf19c0db..0455d9c9a6 100644
--- a/models/migrations/testlogger_test.go
+++ b/models/migrations/testlogger_test.go
@@ -188,5 +188,5 @@ func (log *TestLogger) GetName() string {
 func init() {
 	log.Register("test", NewTestLogger)
 	_, filename, _, _ := runtime.Caller(0)
-	prefix = strings.TrimSuffix(filename, "integrations/testlogger.go")
+	prefix = strings.TrimSuffix(filename, "tests/testlogger.go")
 }
diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go
index 58656f781f..25129137f7 100644
--- a/models/unittest/testdb.go
+++ b/models/unittest/testdb.go
@@ -116,7 +116,7 @@ func MainTest(m *testing.M, testOpts *TestOptions) {
 	if err = util.RemoveAll(repoRootPath); err != nil {
 		fatalTestError("util.RemoveAll: %v\n", err)
 	}
-	if err = CopyDir(filepath.Join(testOpts.GiteaRootPath, "integrations", "gitea-repositories-meta"), setting.RepoRootPath); err != nil {
+	if err = CopyDir(filepath.Join(testOpts.GiteaRootPath, "tests", "gitea-repositories-meta"), setting.RepoRootPath); err != nil {
 		fatalTestError("util.CopyDir: %v\n", err)
 	}
 
@@ -202,7 +202,7 @@ func PrepareTestDatabase() error {
 func PrepareTestEnv(t testing.TB) {
 	assert.NoError(t, PrepareTestDatabase())
 	assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
-	metaPath := filepath.Join(giteaRoot, "integrations", "gitea-repositories-meta")
+	metaPath := filepath.Join(giteaRoot, "tests", "gitea-repositories-meta")
 	assert.NoError(t, CopyDir(metaPath, setting.RepoRootPath))
 	ownerDirs, err := os.ReadDir(setting.RepoRootPath)
 	assert.NoError(t, err)
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index a7cf81250b..370bc21822 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -24,7 +24,7 @@ import (
 var localMetas = map[string]string{
 	"user":     "gogits",
 	"repo":     "gogs",
-	"repoPath": "../../integrations/gitea-repositories-meta/user13/repo11.git/",
+	"repoPath": "../../tests/gitea-repositories-meta/user13/repo11.git/",
 }
 
 func TestMain(m *testing.M) {
diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go
index 732fe1a6be..fdbc291c94 100644
--- a/modules/markup/markdown/markdown_test.go
+++ b/modules/markup/markdown/markdown_test.go
@@ -29,7 +29,7 @@ const (
 var localMetas = map[string]string{
 	"user":     "gogits",
 	"repo":     "gogs",
-	"repoPath": "../../../integrations/gitea-repositories-meta/user13/repo11.git/",
+	"repoPath": "../../../tests/gitea-repositories-meta/user13/repo11.git/",
 }
 
 func TestMain(m *testing.M) {
diff --git a/package-lock.json b/package-lock.json
index 8142eea692..ef534bf879 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -46,6 +46,7 @@
         "wrap-ansi": "8.0.1"
       },
       "devDependencies": {
+        "@playwright/test": "1.25.1",
         "@stoplight/spectral-cli": "6.5.1",
         "eslint": "8.22.0",
         "eslint-plugin-import": "2.26.0",
@@ -1356,6 +1357,22 @@
         "node": ">= 8"
       }
     },
+    "node_modules/@playwright/test": {
+      "version": "1.25.1",
+      "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.25.1.tgz",
+      "integrity": "sha512-IJ4X0yOakXtwkhbnNzKkaIgXe6df7u3H3FnuhI9Jqh+CdO0e/lYQlDLYiyI9cnXK8E7UAppAWP+VqAv6VX7HQg==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*",
+        "playwright-core": "1.25.1"
+      },
+      "bin": {
+        "playwright": "cli.js"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
     "node_modules/@popperjs/core": {
       "version": "2.11.6",
       "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
@@ -9028,6 +9045,18 @@
         "node": ">=8"
       }
     },
+    "node_modules/playwright-core": {
+      "version": "1.25.1",
+      "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.25.1.tgz",
+      "integrity": "sha512-lSvPCmA2n7LawD2Hw7gSCLScZ+vYRkhU8xH0AapMyzwN+ojoDqhkH/KIEUxwNu2PjPoE/fcE0wLAksdOhJ2O5g==",
+      "dev": true,
+      "bin": {
+        "playwright": "cli.js"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
     "node_modules/pluralize": {
       "version": "8.0.0",
       "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
@@ -12789,6 +12818,16 @@
         "fastq": "^1.6.0"
       }
     },
+    "@playwright/test": {
+      "version": "1.25.1",
+      "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.25.1.tgz",
+      "integrity": "sha512-IJ4X0yOakXtwkhbnNzKkaIgXe6df7u3H3FnuhI9Jqh+CdO0e/lYQlDLYiyI9cnXK8E7UAppAWP+VqAv6VX7HQg==",
+      "dev": true,
+      "requires": {
+        "@types/node": "*",
+        "playwright-core": "1.25.1"
+      }
+    },
     "@popperjs/core": {
       "version": "2.11.6",
       "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
@@ -18627,6 +18666,12 @@
         }
       }
     },
+    "playwright-core": {
+      "version": "1.25.1",
+      "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.25.1.tgz",
+      "integrity": "sha512-lSvPCmA2n7LawD2Hw7gSCLScZ+vYRkhU8xH0AapMyzwN+ojoDqhkH/KIEUxwNu2PjPoE/fcE0wLAksdOhJ2O5g==",
+      "dev": true
+    },
     "pluralize": {
       "version": "8.0.0",
       "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
diff --git a/package.json b/package.json
index 3a5cb3f624..5a937ced95 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
     "wrap-ansi": "8.0.1"
   },
   "devDependencies": {
+    "@playwright/test": "1.25.1",
     "@stoplight/spectral-cli": "6.5.1",
     "eslint": "8.22.0",
     "eslint-plugin-import": "2.26.0",
diff --git a/playwright.config.js b/playwright.config.js
new file mode 100644
index 0000000000..af67717a2d
--- /dev/null
+++ b/playwright.config.js
@@ -0,0 +1,100 @@
+// @ts-check
+import {devices} from '@playwright/test';
+
+const BASE_URL = process.env.GITEA_URL?.replace?.(/\/$/g, '') || 'http://localhost:3000';
+
+/**
+ * @see https://playwright.dev/docs/test-configuration
+ * @type {import('@playwright/test').PlaywrightTestConfig}
+ */
+export default {
+  testDir: './tests/e2e/',
+  testMatch: /.*\.test\.e2e\.js/, // Match any .test.e2e.js files
+
+  /* Maximum time one test can run for. */
+  timeout: 30 * 1000,
+
+  expect: {
+
+    /**
+     * Maximum time expect() should wait for the condition to be met.
+     * For example in `await expect(locator).toHaveText();`
+     */
+    timeout: 2000
+  },
+
+  /* Fail the build on CI if you accidentally left test.only in the source code. */
+  forbidOnly: !!process.env.CI,
+
+  /* Retry on CI only */
+  retries: process.env.CI ? 2 : 0,
+
+  /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+  reporter: process.env.CI ? 'list' : [['list'], ['html', {outputFolder: 'tests/e2e/reports/', open: 'never'}]],
+
+  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+  use: {
+    headless: true,   // set to false to debug
+
+    locale: 'en-US',
+
+    /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
+    actionTimeout: 1000,
+
+    /* Maximum time allowed for navigation, such as `page.goto()`. */
+    navigationTimeout: 5 * 1000,
+
+    /* Base URL to use in actions like `await page.goto('/')`. */
+    baseURL: BASE_URL,
+
+    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+    trace: 'on-first-retry',
+
+    screenshot: 'only-on-failure',
+  },
+
+  /* Configure projects for major browsers */
+  projects: [
+    {
+      name: 'chromium',
+
+      /* Project-specific settings. */
+      use: {
+        ...devices['Desktop Chrome'],
+      },
+    },
+
+    {
+      name: 'firefox',
+      use: {
+        ...devices['Desktop Firefox'],
+      },
+    },
+
+    {
+      name: 'webkit',
+      use: {
+        ...devices['Desktop Safari'],
+      },
+    },
+
+    /* Test against mobile viewports. */
+    {
+      name: 'Mobile Chrome',
+      use: {
+        ...devices['Pixel 5'],
+      },
+    },
+    {
+      name: 'Mobile Safari',
+      use: {
+        ...devices['iPhone 12'],
+      },
+    },
+  ],
+
+  /* Folder for test artifacts such as screenshots, videos, traces, etc. */
+  outputDir: 'tests/e2e/test-artifacts/',
+  /* Folder for test artifacts such as screenshots, videos, traces, etc. */
+  snapshotDir: 'tests/e2e/test-snapshots/',
+};
diff --git a/tests/e2e/README.md b/tests/e2e/README.md
new file mode 100644
index 0000000000..c84d7807fc
--- /dev/null
+++ b/tests/e2e/README.md
@@ -0,0 +1,93 @@
+# End to end tests
+
+E2e tests largely follow the same syntax as [integration tests](tests/e2e/README.md). 
+Whereas integration tests are intended to mock and stress the back-end, server-side code, e2e tests the interface between front-end and back-end, as well as visual regressions with both assertions and visual comparisons.
+They can be run with make commands for the appropriate backends, namely:
+```shell
+make test-sqlite
+make test-pgsql
+make test-mysql
+make test-mysql8
+make test-mssql
+```
+
+Make sure to perform a clean front-end build before running tests:
+```
+make clean frontend
+```
+
+## Install playwright system dependencies
+```
+npx playwright install-deps
+```
+
+
+## Run all tests via local drone
+```
+drone exec --local --build-event "pull_request"
+```
+
+## Run sqlite e2e tests
+Start tests
+```
+make test-e2e-sqlite
+```
+
+## Run MySQL e2e tests
+Setup a MySQL database inside docker
+```
+docker run -e "MYSQL_DATABASE=test" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" -p 3306:3306 --rm --name mysql mysql:latest #(just ctrl-c to stop db and clean the container)
+docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --rm --name elasticsearch elasticsearch:7.6.0 #(in a second terminal, just ctrl-c to stop db and clean the container)
+```
+Start tests based on the database container
+```
+TEST_MYSQL_HOST=localhost:3306 TEST_MYSQL_DBNAME=test TEST_MYSQL_USERNAME=root TEST_MYSQL_PASSWORD='' make test-e2e-mysql
+```
+
+## Run pgsql e2e tests
+Setup a pgsql database inside docker
+```
+docker run -e "POSTGRES_DB=test" -p 5432:5432 --rm --name pgsql postgres:latest #(just ctrl-c to stop db and clean the container)
+```
+Start tests based on the database container
+```
+TEST_PGSQL_HOST=localhost:5432 TEST_PGSQL_DBNAME=test TEST_PGSQL_USERNAME=postgres TEST_PGSQL_PASSWORD=postgres make test-e2e-pgsql
+```
+
+## Run mssql e2e tests
+Setup a mssql database inside docker
+```
+docker run -e "ACCEPT_EULA=Y" -e "MSSQL_PID=Standard" -e "SA_PASSWORD=MwantsaSecurePassword1" -p 1433:1433 --rm --name mssql microsoft/mssql-server-linux:latest #(just ctrl-c to stop db and clean the container)
+```
+Start tests based on the database container
+```
+TEST_MSSQL_HOST=localhost:1433 TEST_MSSQL_DBNAME=gitea_test TEST_MSSQL_USERNAME=sa TEST_MSSQL_PASSWORD=MwantsaSecurePassword1 make test-e2e-mssql
+```
+
+## Running individual tests
+
+Example command to run `example.test.e2e.js` test file:
+
+_Note: unlike integration tests, this filtering is at the file level, not function_
+
+For SQLite:
+
+```
+make test-e2e-sqlite#example
+```
+
+For other databases(replace `mssql` to `mysql`, `mysql8` or `pgsql`):
+
+```
+TEST_MSSQL_HOST=localhost:1433 TEST_MSSQL_DBNAME=test TEST_MSSQL_USERNAME=sa TEST_MSSQL_PASSWORD=MwantsaSecurePassword1 make test-e2e-mssql#example
+```
+
+## Visual testing
+
+Although the main goal of e2e is assertion testing, we have added a framework for visual regress testing. If you are working on front-end features, please use the following:
+ - Check out `main`, `make clean frontend`, and run e2e tests with `VISUAL_TEST=1` to generate outputs. This will initially fail, as no screenshots exist. You can run the e2e tests again to assert it passes.
+ - Check out your branch, `make clean frontend`, and run e2e tests with `VISUAL_TEST=1`. You should be able to assert you front-end changes don't break any other tests unintentionally. 
+
+VISUAL_TEST=1 will create screenshots in tests/e2e/test-snapshots. The test will fail the first time this is enabled (until we get visual test image persistence figured out), because it will be testing against an empty screenshot folder. 
+
+ACCEPT_VISUAL=1 will overwrite the snapshot images with new images.
\ No newline at end of file
diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go
new file mode 100644
index 0000000000..c77c071181
--- /dev/null
+++ b/tests/e2e/e2e_test.go
@@ -0,0 +1,120 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+// This is primarily coped from /tests/integration/integration_test.go
+//   TODO: Move common functions to shared file
+
+package e2e
+
+import (
+	"bytes"
+	"context"
+	"fmt"
+	"net/url"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"testing"
+
+	"code.gitea.io/gitea/models/unittest"
+	"code.gitea.io/gitea/modules/graceful"
+	"code.gitea.io/gitea/modules/log"
+	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/modules/web"
+	"code.gitea.io/gitea/routers"
+	"code.gitea.io/gitea/tests"
+)
+
+var c *web.Route
+
+func TestMain(m *testing.M) {
+	defer log.Close()
+
+	managerCtx, cancel := context.WithCancel(context.Background())
+	graceful.InitManager(managerCtx)
+	defer cancel()
+
+	tests.InitTest(false)
+	c = routers.NormalRoutes(context.TODO())
+
+	os.Unsetenv("GIT_AUTHOR_NAME")
+	os.Unsetenv("GIT_AUTHOR_EMAIL")
+	os.Unsetenv("GIT_AUTHOR_DATE")
+	os.Unsetenv("GIT_COMMITTER_NAME")
+	os.Unsetenv("GIT_COMMITTER_EMAIL")
+	os.Unsetenv("GIT_COMMITTER_DATE")
+
+	err := unittest.InitFixtures(
+		unittest.FixturesOptions{
+			Dir: filepath.Join(filepath.Dir(setting.AppPath), "models/fixtures/"),
+		},
+	)
+	if err != nil {
+		fmt.Printf("Error initializing test database: %v\n", err)
+		os.Exit(1)
+	}
+
+	exitVal := m.Run()
+
+	tests.WriterCloser.Reset()
+
+	if err = util.RemoveAll(setting.Indexer.IssuePath); err != nil {
+		fmt.Printf("util.RemoveAll: %v\n", err)
+		os.Exit(1)
+	}
+	if err = util.RemoveAll(setting.Indexer.RepoPath); err != nil {
+		fmt.Printf("Unable to remove repo indexer: %v\n", err)
+		os.Exit(1)
+	}
+
+	os.Exit(exitVal)
+}
+
+// This should be the only test e2e necessary. It will collect all "*.test.e2e.js"
+//   files in this directory and build a test for each.
+func TestE2e(t *testing.T) {
+	// Find the paths of all e2e test files in test test directory.
+	searchGlob := filepath.Join(filepath.Dir(setting.AppPath), "tests", "e2e", "*.test.e2e.js")
+	paths, err := filepath.Glob(searchGlob)
+	if err != nil {
+		t.Fatal(err)
+	} else if len(paths) == 0 {
+		t.Fatal(fmt.Errorf("No e2e tests found in %s", searchGlob))
+	}
+
+	runArgs := []string{"npx", "playwright", "test"}
+
+	// To update snapshot outputs
+	if _, set := os.LookupEnv("ACCEPT_VISUAL"); set {
+		runArgs = append(runArgs, "--update-snapshots")
+	}
+
+	// Create new test for each input file
+	for _, path := range paths {
+		_, filename := filepath.Split(path)
+		testname := filename[:len(filename)-len(filepath.Ext(path))]
+
+		t.Run(testname, func(t *testing.T) {
+			// Default 2 minute timeout
+			onGiteaRun(t, func(*testing.T, *url.URL) {
+				cmd := exec.Command(runArgs[0], runArgs...)
+				cmd.Env = os.Environ()
+				cmd.Env = append(cmd.Env, fmt.Sprintf("GITEA_URL=%s", setting.AppURL))
+				var stdout, stderr bytes.Buffer
+				cmd.Stdout = &stdout
+				cmd.Stderr = &stderr
+				err := cmd.Run()
+				if err != nil {
+					// Currently colored output is conflicting. Using Printf until that is resolved.
+					fmt.Printf("%v", stdout.String())
+					fmt.Printf("%v", stderr.String())
+					log.Fatal("Playwright Failed: %s", err)
+				} else {
+					fmt.Printf("%v", stdout.String())
+				}
+			})
+		})
+	}
+}
diff --git a/tests/e2e/example.test.e2e.js b/tests/e2e/example.test.e2e.js
new file mode 100644
index 0000000000..bd19ceb8fc
--- /dev/null
+++ b/tests/e2e/example.test.e2e.js
@@ -0,0 +1,57 @@
+// @ts-check
+import {test, expect} from '@playwright/test';
+import {login_user, save_visual, load_logged_in_context} from './utils_e2e.js';
+
+test.beforeAll(async ({browser}, workerInfo) => {
+  await login_user(browser, workerInfo, 'user2');
+});
+
+test('Load Homepage', async ({page}) => {
+  const response = await page.goto('/');
+  await expect(response?.status()).toBe(200); // Status OK
+  await expect(page).toHaveTitle(/^Gitea: Git with a cup of tea\s*$/);
+  await expect(page.locator('.logo')).toHaveAttribute('src', '/assets/img/logo.svg');
+});
+
+test('Test Register Form', async ({page}, workerInfo) => {
+  const response = await page.goto('/user/sign_up');
+  await expect(response?.status()).toBe(200); // Status OK
+  await page.type('input[name=user_name]', `e2e-test-${workerInfo.workerIndex}`);
+  await page.type('input[name=email]', `e2e-test-${workerInfo.workerIndex}@test.com`);
+  await page.type('input[name=password]', 'test123');
+  await page.type('input[name=retype]', 'test123');
+  await page.click('form button.ui.green.button:visible');
+  // Make sure we routed to the home page. Else login failed.
+  await expect(page.url()).toBe(`${workerInfo.project.use.baseURL}/`);
+  await expect(page.locator('.dashboard-navbar span>img.ui.avatar.image')).toBeVisible();
+  await expect(page.locator('.ui.positive.message.flash-success')).toHaveText('Account was successfully created.');
+
+  save_visual(page);
+});
+
+test('Test Login Form', async ({page}, workerInfo) => {
+  const response = await page.goto('/user/login');
+  await expect(response?.status()).toBe(200); // Status OK
+
+  await page.type('input[name=user_name]', `user2`);
+  await page.type('input[name=password]', `password`);
+  await page.click('form button.ui.green.button:visible');
+
+  await page.waitForLoadState('networkidle');
+
+  await expect(page.url()).toBe(`${workerInfo.project.use.baseURL}/`);
+
+  save_visual(page);
+});
+
+test('Test Logged In User', async ({browser}, workerInfo) => {
+  const context = await load_logged_in_context(browser, workerInfo, 'user2');
+  const page = await context.newPage();
+
+  await page.goto('/');
+
+  // Make sure we routed to the home page. Else login failed.
+  await expect(page.url()).toBe(`${workerInfo.project.use.baseURL}/`);
+
+  save_visual(page);
+});
diff --git a/tests/e2e/utils_e2e.js b/tests/e2e/utils_e2e.js
new file mode 100644
index 0000000000..b5b9ce2751
--- /dev/null
+++ b/tests/e2e/utils_e2e.js
@@ -0,0 +1,60 @@
+import {expect} from '@playwright/test';
+
+const ARTIFACTS_PATH = `tests/e2e/test-artifacts`;
+const LOGIN_PASSWORD = 'password';
+
+// log in user and store session info. This should generally be
+//  run in test.beforeAll(), then the session can be loaded in tests.
+export async function login_user(browser, workerInfo, user) {
+  // Set up a new context
+  const context = await browser.newContext();
+  const page = await context.newPage();
+
+  // Route to login page
+  // Note: this could probably be done more quickly with a POST
+  const response = await page.goto('/user/login');
+  await expect(response?.status()).toBe(200); // Status OK
+
+  // Fill out form
+  await page.type('input[name=user_name]', user);
+  await page.type('input[name=password]', LOGIN_PASSWORD);
+  await page.click('form button.ui.green.button:visible');
+
+  await page.waitForLoadState('networkidle');
+
+  await expect(page.url(), {message: `Failed to login user ${user}`}).toBe(`${workerInfo.project.use.baseURL}/`);
+
+  // Save state
+  await context.storageState({path: `${ARTIFACTS_PATH}/state-${user}-${workerInfo.workerIndex}.json`});
+
+  return context;
+}
+
+export async function load_logged_in_context(browser, workerInfo, user) {
+  let context;
+  try {
+    context = await browser.newContext({storageState: `${ARTIFACTS_PATH}/state-${user}-${workerInfo.workerIndex}.json`});
+  } catch (err) {
+    if (err.code === 'ENOENT') {
+      throw new Error(`Could not find state for '${user}'. Did you call login_user(browser, workerInfo, '${user}') in test.beforeAll()?`);
+    }
+  }
+  return context;
+}
+
+export async function save_visual(page) {
+  // Optionally include visual testing
+  if (process.env.VISUAL_TEST) {
+    await page.waitForLoadState('networkidle');
+    // Mock page/version string
+    await page.locator('footer div.ui.left').evaluate((node) => node.innerHTML = 'MOCK');
+    await expect(page).toHaveScreenshot({
+      fullPage: true,
+      timeout: 20000,
+      mask: [
+        page.locator('.dashboard-navbar span>img.ui.avatar.image'),
+        page.locator('.ui.dropdown.jump.item.tooltip span>img.ui.avatar.image'),
+      ],
+    });
+  }
+}
diff --git a/tests/e2e/utils_e2e_test.go b/tests/e2e/utils_e2e_test.go
new file mode 100644
index 0000000000..f8f3e94cda
--- /dev/null
+++ b/tests/e2e/utils_e2e_test.go
@@ -0,0 +1,57 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package e2e
+
+import (
+	"context"
+	"net"
+	"net/http"
+	"net/url"
+	"testing"
+	"time"
+
+	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func onGiteaRunTB(t testing.TB, callback func(testing.TB, *url.URL), prepare ...bool) {
+	if len(prepare) == 0 || prepare[0] {
+		defer tests.PrepareTestEnv(t, 1)()
+	}
+	s := http.Server{
+		Handler: c,
+	}
+
+	u, err := url.Parse(setting.AppURL)
+	assert.NoError(t, err)
+	listener, err := net.Listen("tcp", u.Host)
+	i := 0
+	for err != nil && i <= 10 {
+		time.Sleep(100 * time.Millisecond)
+		listener, err = net.Listen("tcp", u.Host)
+		i++
+	}
+	assert.NoError(t, err)
+	u.Host = listener.Addr().String()
+
+	defer func() {
+		ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
+		s.Shutdown(ctx)
+		cancel()
+	}()
+
+	go s.Serve(listener)
+	// Started by config go ssh.Listen(setting.SSH.ListenHost, setting.SSH.ListenPort, setting.SSH.ServerCiphers, setting.SSH.ServerKeyExchanges, setting.SSH.ServerMACs)
+
+	callback(t, u)
+}
+
+func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL), prepare ...bool) {
+	onGiteaRunTB(t, func(t testing.TB, u *url.URL) {
+		callback(t.(*testing.T), u)
+	}, prepare...)
+}
diff --git a/integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/HEAD b/tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/HEAD
rename to tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/HEAD
diff --git a/integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/config b/tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/config
rename to tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/config
diff --git a/integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/description b/tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/description
rename to tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/description
diff --git a/integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/info/exclude b/tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/info/exclude
rename to tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/74/8bf557dfc9c6457998b5118a6c8b2129f56c30 b/tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/74/8bf557dfc9c6457998b5118a6c8b2129f56c30
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/74/8bf557dfc9c6457998b5118a6c8b2129f56c30
rename to tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/74/8bf557dfc9c6457998b5118a6c8b2129f56c30
diff --git a/integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/a5/46f86c7dd182592b96639045e176dde8df76ef b/tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/a5/46f86c7dd182592b96639045e176dde8df76ef
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/a5/46f86c7dd182592b96639045e176dde8df76ef
rename to tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/a5/46f86c7dd182592b96639045e176dde8df76ef
diff --git a/integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/b8/95782bd271fdd266dd06e5880ea4abdc3a0dc7 b/tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/b8/95782bd271fdd266dd06e5880ea4abdc3a0dc7
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/b8/95782bd271fdd266dd06e5880ea4abdc3a0dc7
rename to tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/objects/b8/95782bd271fdd266dd06e5880ea4abdc3a0dc7
diff --git a/integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/refs/heads/master b/tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/refs/heads/master
rename to tests/gitea-repositories-meta/limited_org/private_repo_on_limited_org.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/HEAD b/tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/HEAD
rename to tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/HEAD
diff --git a/integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/config b/tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/config
rename to tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/config
diff --git a/integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/description b/tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/description
rename to tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/description
diff --git a/integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/info/exclude b/tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/info/exclude
rename to tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/21/2f14c8b713de38bd0b3fb23bd288369b01668a b/tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/21/2f14c8b713de38bd0b3fb23bd288369b01668a
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/21/2f14c8b713de38bd0b3fb23bd288369b01668a
rename to tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/21/2f14c8b713de38bd0b3fb23bd288369b01668a
diff --git a/integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/90/e402c3937a4639725fcc59ca1f529e7dc8506f b/tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/90/e402c3937a4639725fcc59ca1f529e7dc8506f
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/90/e402c3937a4639725fcc59ca1f529e7dc8506f
rename to tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/90/e402c3937a4639725fcc59ca1f529e7dc8506f
diff --git a/integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/ed/d9c1000cd1444efd63e153e3554c8d5656bf65 b/tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/ed/d9c1000cd1444efd63e153e3554c8d5656bf65
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/ed/d9c1000cd1444efd63e153e3554c8d5656bf65
rename to tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/objects/ed/d9c1000cd1444efd63e153e3554c8d5656bf65
diff --git a/integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/refs/heads/master b/tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/refs/heads/master
rename to tests/gitea-repositories-meta/limited_org/public_repo_on_limited_org.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/HEAD b/tests/gitea-repositories-meta/migration/lfs-test.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/HEAD
rename to tests/gitea-repositories-meta/migration/lfs-test.git/HEAD
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/config b/tests/gitea-repositories-meta/migration/lfs-test.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/config
rename to tests/gitea-repositories-meta/migration/lfs-test.git/config
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/description b/tests/gitea-repositories-meta/migration/lfs-test.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/description
rename to tests/gitea-repositories-meta/migration/lfs-test.git/description
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/hooks/post-checkout b/tests/gitea-repositories-meta/migration/lfs-test.git/hooks/post-checkout
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/hooks/post-checkout
rename to tests/gitea-repositories-meta/migration/lfs-test.git/hooks/post-checkout
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/hooks/post-commit b/tests/gitea-repositories-meta/migration/lfs-test.git/hooks/post-commit
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/hooks/post-commit
rename to tests/gitea-repositories-meta/migration/lfs-test.git/hooks/post-commit
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/hooks/post-merge b/tests/gitea-repositories-meta/migration/lfs-test.git/hooks/post-merge
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/hooks/post-merge
rename to tests/gitea-repositories-meta/migration/lfs-test.git/hooks/post-merge
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/hooks/pre-push b/tests/gitea-repositories-meta/migration/lfs-test.git/hooks/pre-push
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/hooks/pre-push
rename to tests/gitea-repositories-meta/migration/lfs-test.git/hooks/pre-push
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/index b/tests/gitea-repositories-meta/migration/lfs-test.git/index
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/index
rename to tests/gitea-repositories-meta/migration/lfs-test.git/index
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/lfs/objects/d6/f1/d6f175817f886ec6fbbc1515326465fa96c3bfd54a4ea06cfd6dbbd8340e0152 b/tests/gitea-repositories-meta/migration/lfs-test.git/lfs/objects/d6/f1/d6f175817f886ec6fbbc1515326465fa96c3bfd54a4ea06cfd6dbbd8340e0152
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/lfs/objects/d6/f1/d6f175817f886ec6fbbc1515326465fa96c3bfd54a4ea06cfd6dbbd8340e0152
rename to tests/gitea-repositories-meta/migration/lfs-test.git/lfs/objects/d6/f1/d6f175817f886ec6fbbc1515326465fa96c3bfd54a4ea06cfd6dbbd8340e0152
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/lfs/objects/fb/8f/fb8f7d8435968c4f82a726a92395be4d16f2f63116caf36c8ad35c60831ab041 b/tests/gitea-repositories-meta/migration/lfs-test.git/lfs/objects/fb/8f/fb8f7d8435968c4f82a726a92395be4d16f2f63116caf36c8ad35c60831ab041
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/lfs/objects/fb/8f/fb8f7d8435968c4f82a726a92395be4d16f2f63116caf36c8ad35c60831ab041
rename to tests/gitea-repositories-meta/migration/lfs-test.git/lfs/objects/fb/8f/fb8f7d8435968c4f82a726a92395be4d16f2f63116caf36c8ad35c60831ab041
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/objects/54/6244003622c64b2fc3c2cd544d7a29882c8383 b/tests/gitea-repositories-meta/migration/lfs-test.git/objects/54/6244003622c64b2fc3c2cd544d7a29882c8383
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/objects/54/6244003622c64b2fc3c2cd544d7a29882c8383
rename to tests/gitea-repositories-meta/migration/lfs-test.git/objects/54/6244003622c64b2fc3c2cd544d7a29882c8383
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/objects/6a/6ccf5d874fec134ee712572cc03a0f2dd7afec b/tests/gitea-repositories-meta/migration/lfs-test.git/objects/6a/6ccf5d874fec134ee712572cc03a0f2dd7afec
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/objects/6a/6ccf5d874fec134ee712572cc03a0f2dd7afec
rename to tests/gitea-repositories-meta/migration/lfs-test.git/objects/6a/6ccf5d874fec134ee712572cc03a0f2dd7afec
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/objects/a6/7134b8484c2abe9fa954e1fd83b39b271383ed b/tests/gitea-repositories-meta/migration/lfs-test.git/objects/a6/7134b8484c2abe9fa954e1fd83b39b271383ed
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/objects/a6/7134b8484c2abe9fa954e1fd83b39b271383ed
rename to tests/gitea-repositories-meta/migration/lfs-test.git/objects/a6/7134b8484c2abe9fa954e1fd83b39b271383ed
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/objects/b7/01ed6ffe410f0c3ac204b929ea47cfec6cef54 b/tests/gitea-repositories-meta/migration/lfs-test.git/objects/b7/01ed6ffe410f0c3ac204b929ea47cfec6cef54
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/objects/b7/01ed6ffe410f0c3ac204b929ea47cfec6cef54
rename to tests/gitea-repositories-meta/migration/lfs-test.git/objects/b7/01ed6ffe410f0c3ac204b929ea47cfec6cef54
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/objects/f2/07b74f55cd7f9e800b7550d587cbc488f6eaf1 b/tests/gitea-repositories-meta/migration/lfs-test.git/objects/f2/07b74f55cd7f9e800b7550d587cbc488f6eaf1
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/objects/f2/07b74f55cd7f9e800b7550d587cbc488f6eaf1
rename to tests/gitea-repositories-meta/migration/lfs-test.git/objects/f2/07b74f55cd7f9e800b7550d587cbc488f6eaf1
diff --git a/integrations/gitea-repositories-meta/migration/lfs-test.git/refs/heads/master b/tests/gitea-repositories-meta/migration/lfs-test.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/migration/lfs-test.git/refs/heads/master
rename to tests/gitea-repositories-meta/migration/lfs-test.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/COMMITMESSAGE b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/COMMITMESSAGE
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/COMMITMESSAGE
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/COMMITMESSAGE
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/COMMIT_EDITMSG b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/COMMIT_EDITMSG
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/COMMIT_EDITMSG
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/COMMIT_EDITMSG
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/HEAD b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/HEAD
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/HEAD
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/config b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/config
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/config
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/config.backup b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/config.backup
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/config.backup
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/config.backup
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/description b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/description
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/description
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/index b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/index
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/index
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/index
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/info/exclude b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/info/exclude
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/logs/HEAD b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/logs/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/logs/HEAD
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/logs/HEAD
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/logs/refs/heads/branch1 b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/logs/refs/heads/branch1
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/logs/refs/heads/branch1
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/logs/refs/heads/branch1
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/logs/refs/heads/master b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/logs/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/logs/refs/heads/master
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/logs/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855 b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/refs/heads/branch1 b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/refs/heads/branch1
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/refs/heads/branch1
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/refs/heads/branch1
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker.git/refs/heads/master b/tests/gitea-repositories-meta/org26/repo_external_tracker.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker.git/refs/heads/master
rename to tests/gitea-repositories-meta/org26/repo_external_tracker.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/COMMITMESSAGE b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/COMMITMESSAGE
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/COMMITMESSAGE
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/COMMITMESSAGE
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/COMMIT_EDITMSG b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/COMMIT_EDITMSG
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/COMMIT_EDITMSG
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/COMMIT_EDITMSG
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/HEAD b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/HEAD
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/HEAD
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/config b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/config
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/config
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/config.backup b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/config.backup
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/config.backup
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/config.backup
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/description b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/description
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/description
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/index b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/index
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/index
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/index
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/info/exclude b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/info/exclude
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/HEAD b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/HEAD
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/HEAD
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/refs/heads/branch1 b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/refs/heads/branch1
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/refs/heads/branch1
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/refs/heads/branch1
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/refs/heads/master b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/refs/heads/master
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/logs/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855 b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/refs/heads/branch1 b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/refs/heads/branch1
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/refs/heads/branch1
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/refs/heads/branch1
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/refs/heads/master b/tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/refs/heads/master
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_alpha.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/COMMITMESSAGE b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/COMMITMESSAGE
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/COMMITMESSAGE
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/COMMITMESSAGE
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/COMMIT_EDITMSG b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/COMMIT_EDITMSG
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/COMMIT_EDITMSG
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/COMMIT_EDITMSG
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/HEAD b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/HEAD
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/HEAD
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/config b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/config
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/config
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/config.backup b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/config.backup
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/config.backup
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/config.backup
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/description b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/description
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/description
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/index b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/index
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/index
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/index
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/info/exclude b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/info/exclude
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/HEAD b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/HEAD
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/HEAD
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/refs/heads/branch1 b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/refs/heads/branch1
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/refs/heads/branch1
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/refs/heads/branch1
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/refs/heads/master b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/refs/heads/master
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/logs/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855 b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/ba/ea7d6e6b7773a80bcede323cfb21dfe9d4b855
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/c2/a1ad4c931cebe27c7e39176fe7119b5557c9eb
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/objects/cd/aca8cf1d36e1e4e508a940f6e157e239beccfa
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/refs/heads/branch1 b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/refs/heads/branch1
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/refs/heads/branch1
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/refs/heads/branch1
diff --git a/integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/refs/heads/master b/tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/refs/heads/master
rename to tests/gitea-repositories-meta/org26/repo_external_tracker_numeric.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/HEAD b/tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/HEAD
rename to tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/HEAD
diff --git a/integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/config b/tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/config
rename to tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/config
diff --git a/integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/description b/tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/description
rename to tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/description
diff --git a/integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/info/exclude b/tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/info/exclude
rename to tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/6e/75c9f89da9a9b93f4f36e61ed092f7a1625ba0 b/tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/6e/75c9f89da9a9b93f4f36e61ed092f7a1625ba0
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/6e/75c9f89da9a9b93f4f36e61ed092f7a1625ba0
rename to tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/6e/75c9f89da9a9b93f4f36e61ed092f7a1625ba0
diff --git a/integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/7f/eb6f9dd600e17a04f48a76cfa0a56a3f30e2c1 b/tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/7f/eb6f9dd600e17a04f48a76cfa0a56a3f30e2c1
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/7f/eb6f9dd600e17a04f48a76cfa0a56a3f30e2c1
rename to tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/7f/eb6f9dd600e17a04f48a76cfa0a56a3f30e2c1
diff --git a/integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/b7/91b41c0ae8cb3c4b12f3fd8c3709c2481d9e37 b/tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/b7/91b41c0ae8cb3c4b12f3fd8c3709c2481d9e37
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/b7/91b41c0ae8cb3c4b12f3fd8c3709c2481d9e37
rename to tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/objects/b7/91b41c0ae8cb3c4b12f3fd8c3709c2481d9e37
diff --git a/integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/refs/heads/master b/tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/refs/heads/master
rename to tests/gitea-repositories-meta/privated_org/private_repo_on_private_org.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/HEAD b/tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/HEAD
rename to tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/HEAD
diff --git a/integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/config b/tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/config
rename to tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/config
diff --git a/integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/description b/tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/description
rename to tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/description
diff --git a/integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/info/exclude b/tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/info/exclude
rename to tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/04/f99c528b643b9175a4b156cdfc13aba6b43853 b/tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/04/f99c528b643b9175a4b156cdfc13aba6b43853
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/04/f99c528b643b9175a4b156cdfc13aba6b43853
rename to tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/04/f99c528b643b9175a4b156cdfc13aba6b43853
diff --git a/integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/86/de16d8658f5c0a17ec6aa313871295d7072f78 b/tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/86/de16d8658f5c0a17ec6aa313871295d7072f78
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/86/de16d8658f5c0a17ec6aa313871295d7072f78
rename to tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/86/de16d8658f5c0a17ec6aa313871295d7072f78
diff --git a/integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/bf/19fd4707acb403c4aca44f126ab69142ac59ce b/tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/bf/19fd4707acb403c4aca44f126ab69142ac59ce
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/bf/19fd4707acb403c4aca44f126ab69142ac59ce
rename to tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/objects/bf/19fd4707acb403c4aca44f126ab69142ac59ce
diff --git a/integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/refs/heads/master b/tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/refs/heads/master
rename to tests/gitea-repositories-meta/privated_org/public_repo_on_private_org.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/HEAD b/tests/gitea-repositories-meta/user12/repo10.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/HEAD
rename to tests/gitea-repositories-meta/user12/repo10.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/config b/tests/gitea-repositories-meta/user12/repo10.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/config
rename to tests/gitea-repositories-meta/user12/repo10.git/config
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/description b/tests/gitea-repositories-meta/user12/repo10.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/description
rename to tests/gitea-repositories-meta/user12/repo10.git/description
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/hooks/post-receive b/tests/gitea-repositories-meta/user12/repo10.git/hooks/post-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/hooks/post-receive
rename to tests/gitea-repositories-meta/user12/repo10.git/hooks/post-receive
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/hooks/post-receive.d/gitea b/tests/gitea-repositories-meta/user12/repo10.git/hooks/post-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/hooks/post-receive.d/gitea
rename to tests/gitea-repositories-meta/user12/repo10.git/hooks/post-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/hooks/pre-receive b/tests/gitea-repositories-meta/user12/repo10.git/hooks/pre-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/hooks/pre-receive
rename to tests/gitea-repositories-meta/user12/repo10.git/hooks/pre-receive
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/hooks/pre-receive.d/gitea b/tests/gitea-repositories-meta/user12/repo10.git/hooks/pre-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/hooks/pre-receive.d/gitea
rename to tests/gitea-repositories-meta/user12/repo10.git/hooks/pre-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/hooks/update b/tests/gitea-repositories-meta/user12/repo10.git/hooks/update
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/hooks/update
rename to tests/gitea-repositories-meta/user12/repo10.git/hooks/update
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/hooks/update.d/gitea b/tests/gitea-repositories-meta/user12/repo10.git/hooks/update.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/hooks/update.d/gitea
rename to tests/gitea-repositories-meta/user12/repo10.git/hooks/update.d/gitea
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/info/exclude b/tests/gitea-repositories-meta/user12/repo10.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/info/exclude
rename to tests/gitea-repositories-meta/user12/repo10.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/info/refs b/tests/gitea-repositories-meta/user12/repo10.git/info/refs
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/info/refs
rename to tests/gitea-repositories-meta/user12/repo10.git/info/refs
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6 b/tests/gitea-repositories-meta/user12/repo10.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
rename to tests/gitea-repositories-meta/user12/repo10.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f b/tests/gitea-repositories-meta/user12/repo10.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
rename to tests/gitea-repositories-meta/user12/repo10.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d b/tests/gitea-repositories-meta/user12/repo10.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
rename to tests/gitea-repositories-meta/user12/repo10.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/objects/info/packs b/tests/gitea-repositories-meta/user12/repo10.git/objects/info/packs
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/objects/info/packs
rename to tests/gitea-repositories-meta/user12/repo10.git/objects/info/packs
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/refs/heads/DefaultBranch b/tests/gitea-repositories-meta/user12/repo10.git/refs/heads/DefaultBranch
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/refs/heads/DefaultBranch
rename to tests/gitea-repositories-meta/user12/repo10.git/refs/heads/DefaultBranch
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/refs/heads/develop b/tests/gitea-repositories-meta/user12/repo10.git/refs/heads/develop
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/refs/heads/develop
rename to tests/gitea-repositories-meta/user12/repo10.git/refs/heads/develop
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/refs/heads/feature/1 b/tests/gitea-repositories-meta/user12/repo10.git/refs/heads/feature/1
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/refs/heads/feature/1
rename to tests/gitea-repositories-meta/user12/repo10.git/refs/heads/feature/1
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/refs/heads/master b/tests/gitea-repositories-meta/user12/repo10.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/refs/heads/master
rename to tests/gitea-repositories-meta/user12/repo10.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user12/repo10.git/refs/tags/v1.1 b/tests/gitea-repositories-meta/user12/repo10.git/refs/tags/v1.1
similarity index 100%
rename from integrations/gitea-repositories-meta/user12/repo10.git/refs/tags/v1.1
rename to tests/gitea-repositories-meta/user12/repo10.git/refs/tags/v1.1
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/HEAD b/tests/gitea-repositories-meta/user13/repo11.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/HEAD
rename to tests/gitea-repositories-meta/user13/repo11.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/config b/tests/gitea-repositories-meta/user13/repo11.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/config
rename to tests/gitea-repositories-meta/user13/repo11.git/config
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/description b/tests/gitea-repositories-meta/user13/repo11.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/description
rename to tests/gitea-repositories-meta/user13/repo11.git/description
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/hooks/post-receive b/tests/gitea-repositories-meta/user13/repo11.git/hooks/post-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/hooks/post-receive
rename to tests/gitea-repositories-meta/user13/repo11.git/hooks/post-receive
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/hooks/post-receive.d/gitea b/tests/gitea-repositories-meta/user13/repo11.git/hooks/post-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/hooks/post-receive.d/gitea
rename to tests/gitea-repositories-meta/user13/repo11.git/hooks/post-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/hooks/pre-receive b/tests/gitea-repositories-meta/user13/repo11.git/hooks/pre-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/hooks/pre-receive
rename to tests/gitea-repositories-meta/user13/repo11.git/hooks/pre-receive
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/hooks/pre-receive.d/gitea b/tests/gitea-repositories-meta/user13/repo11.git/hooks/pre-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/hooks/pre-receive.d/gitea
rename to tests/gitea-repositories-meta/user13/repo11.git/hooks/pre-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/hooks/update b/tests/gitea-repositories-meta/user13/repo11.git/hooks/update
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/hooks/update
rename to tests/gitea-repositories-meta/user13/repo11.git/hooks/update
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/hooks/update.d/gitea b/tests/gitea-repositories-meta/user13/repo11.git/hooks/update.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/hooks/update.d/gitea
rename to tests/gitea-repositories-meta/user13/repo11.git/hooks/update.d/gitea
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/info/exclude b/tests/gitea-repositories-meta/user13/repo11.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/info/exclude
rename to tests/gitea-repositories-meta/user13/repo11.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/info/refs b/tests/gitea-repositories-meta/user13/repo11.git/info/refs
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/info/refs
rename to tests/gitea-repositories-meta/user13/repo11.git/info/refs
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/objects/0a/bcb056019adb8336cf9db3ad9d9cf80cd4b141 b/tests/gitea-repositories-meta/user13/repo11.git/objects/0a/bcb056019adb8336cf9db3ad9d9cf80cd4b141
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/objects/0a/bcb056019adb8336cf9db3ad9d9cf80cd4b141
rename to tests/gitea-repositories-meta/user13/repo11.git/objects/0a/bcb056019adb8336cf9db3ad9d9cf80cd4b141
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6 b/tests/gitea-repositories-meta/user13/repo11.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
rename to tests/gitea-repositories-meta/user13/repo11.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f b/tests/gitea-repositories-meta/user13/repo11.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
rename to tests/gitea-repositories-meta/user13/repo11.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d b/tests/gitea-repositories-meta/user13/repo11.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
rename to tests/gitea-repositories-meta/user13/repo11.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/objects/75/d1afd00e111c8dbd9e3d96a27b431ac5ae6d74 b/tests/gitea-repositories-meta/user13/repo11.git/objects/75/d1afd00e111c8dbd9e3d96a27b431ac5ae6d74
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/objects/75/d1afd00e111c8dbd9e3d96a27b431ac5ae6d74
rename to tests/gitea-repositories-meta/user13/repo11.git/objects/75/d1afd00e111c8dbd9e3d96a27b431ac5ae6d74
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/objects/ed/447543e0c85d628b91f7f466f4921908f4c5ea b/tests/gitea-repositories-meta/user13/repo11.git/objects/ed/447543e0c85d628b91f7f466f4921908f4c5ea
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/objects/ed/447543e0c85d628b91f7f466f4921908f4c5ea
rename to tests/gitea-repositories-meta/user13/repo11.git/objects/ed/447543e0c85d628b91f7f466f4921908f4c5ea
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/objects/info/packs b/tests/gitea-repositories-meta/user13/repo11.git/objects/info/packs
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/objects/info/packs
rename to tests/gitea-repositories-meta/user13/repo11.git/objects/info/packs
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/refs/heads/DefaultBranch b/tests/gitea-repositories-meta/user13/repo11.git/refs/heads/DefaultBranch
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/refs/heads/DefaultBranch
rename to tests/gitea-repositories-meta/user13/repo11.git/refs/heads/DefaultBranch
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/refs/heads/branch2 b/tests/gitea-repositories-meta/user13/repo11.git/refs/heads/branch2
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/refs/heads/branch2
rename to tests/gitea-repositories-meta/user13/repo11.git/refs/heads/branch2
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/refs/heads/develop b/tests/gitea-repositories-meta/user13/repo11.git/refs/heads/develop
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/refs/heads/develop
rename to tests/gitea-repositories-meta/user13/repo11.git/refs/heads/develop
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/refs/heads/feature/1 b/tests/gitea-repositories-meta/user13/repo11.git/refs/heads/feature/1
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/refs/heads/feature/1
rename to tests/gitea-repositories-meta/user13/repo11.git/refs/heads/feature/1
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/refs/heads/master b/tests/gitea-repositories-meta/user13/repo11.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/refs/heads/master
rename to tests/gitea-repositories-meta/user13/repo11.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user13/repo11.git/refs/tags/v1.1 b/tests/gitea-repositories-meta/user13/repo11.git/refs/tags/v1.1
similarity index 100%
rename from integrations/gitea-repositories-meta/user13/repo11.git/refs/tags/v1.1
rename to tests/gitea-repositories-meta/user13/repo11.git/refs/tags/v1.1
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/HEAD b/tests/gitea-repositories-meta/user2/commits_search_test.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/HEAD
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/config b/tests/gitea-repositories-meta/user2/commits_search_test.git/config
similarity index 53%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/config
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/config
index 9ec7812f91..bfbada5989 100644
--- a/integrations/gitea-repositories-meta/user2/commits_search_test.git/config
+++ b/tests/gitea-repositories-meta/user2/commits_search_test.git/config
@@ -3,6 +3,6 @@
 	filemode = true
 	bare = true
 [remote "origin"]
-	url = /home/mura/go/src/code.gitea.io/gitea/integrations/gitea-repositories-meta/user2/commits_search_test/
+	url = /home/mura/go/src/code.gitea.io/gitea/tests/gitea-repositories-meta/user2/commits_search_test/
 	fetch = +refs/*:refs/*
 	mirror = true
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/description b/tests/gitea-repositories-meta/user2/commits_search_test.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/description
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/description
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/info/exclude b/tests/gitea-repositories-meta/user2/commits_search_test.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/info/exclude
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/0a/8499a22ad32a80beda9d75efe15f9f94582468 b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/0a/8499a22ad32a80beda9d75efe15f9f94582468
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/0a/8499a22ad32a80beda9d75efe15f9f94582468
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/0a/8499a22ad32a80beda9d75efe15f9f94582468
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/0c/cf1fcd4d1717c22de0707619a5577ea0acebf0 b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/0c/cf1fcd4d1717c22de0707619a5577ea0acebf0
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/0c/cf1fcd4d1717c22de0707619a5577ea0acebf0
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/0c/cf1fcd4d1717c22de0707619a5577ea0acebf0
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/3e/a192a6466793d4b7cd8641801ca0c6bec3979c b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/3e/a192a6466793d4b7cd8641801ca0c6bec3979c
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/3e/a192a6466793d4b7cd8641801ca0c6bec3979c
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/3e/a192a6466793d4b7cd8641801ca0c6bec3979c
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/3f/6594f108842b7c50772510e53ce113d3583c4a b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/3f/6594f108842b7c50772510e53ce113d3583c4a
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/3f/6594f108842b7c50772510e53ce113d3583c4a
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/3f/6594f108842b7c50772510e53ce113d3583c4a
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/58/e97d1a24fb9e1599d8a467ec409430f3d3569e b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/58/e97d1a24fb9e1599d8a467ec409430f3d3569e
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/58/e97d1a24fb9e1599d8a467ec409430f3d3569e
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/58/e97d1a24fb9e1599d8a467ec409430f3d3569e
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/67/68c1fc1d9448422f05cc84267d94ee62085fe8 b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/67/68c1fc1d9448422f05cc84267d94ee62085fe8
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/67/68c1fc1d9448422f05cc84267d94ee62085fe8
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/67/68c1fc1d9448422f05cc84267d94ee62085fe8
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/6e/8eabd9a7f8d6acd2a1219facfd37415564b144 b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/6e/8eabd9a7f8d6acd2a1219facfd37415564b144
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/6e/8eabd9a7f8d6acd2a1219facfd37415564b144
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/6e/8eabd9a7f8d6acd2a1219facfd37415564b144
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/85/f46d747a68adf79cc01e2c25ba6a56932d298d b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/85/f46d747a68adf79cc01e2c25ba6a56932d298d
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/85/f46d747a68adf79cc01e2c25ba6a56932d298d
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/85/f46d747a68adf79cc01e2c25ba6a56932d298d
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/8d/dd8d1ad1fdc21ab629e906711fa9bc27aa1c52 b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/8d/dd8d1ad1fdc21ab629e906711fa9bc27aa1c52
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/8d/dd8d1ad1fdc21ab629e906711fa9bc27aa1c52
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/8d/dd8d1ad1fdc21ab629e906711fa9bc27aa1c52
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/95/fd0c4138480e4b3913e7cf71a90623fb926fe8 b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/95/fd0c4138480e4b3913e7cf71a90623fb926fe8
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/95/fd0c4138480e4b3913e7cf71a90623fb926fe8
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/95/fd0c4138480e4b3913e7cf71a90623fb926fe8
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/98/00fe78cabf4fe774fcf376f97fa2a0ed06987b b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/98/00fe78cabf4fe774fcf376f97fa2a0ed06987b
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/98/00fe78cabf4fe774fcf376f97fa2a0ed06987b
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/98/00fe78cabf4fe774fcf376f97fa2a0ed06987b
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/9f/cdb7d53bdef786d2e5577948a0c0d4b321fe5a b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/9f/cdb7d53bdef786d2e5577948a0c0d4b321fe5a
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/9f/cdb7d53bdef786d2e5577948a0c0d4b321fe5a
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/9f/cdb7d53bdef786d2e5577948a0c0d4b321fe5a
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/c2/0caf78b5f9dd2d0d183876c5cd0e761c13f7f8 b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/c2/0caf78b5f9dd2d0d183876c5cd0e761c13f7f8
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/c2/0caf78b5f9dd2d0d183876c5cd0e761c13f7f8
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/c2/0caf78b5f9dd2d0d183876c5cd0e761c13f7f8
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/c5/2ba74685f5c8c593efbbb38f62fe024110adef b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/c5/2ba74685f5c8c593efbbb38f62fe024110adef
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/c5/2ba74685f5c8c593efbbb38f62fe024110adef
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/c5/2ba74685f5c8c593efbbb38f62fe024110adef
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/d6/ae8023a10ff446b6a4e7f441554834008e99c3 b/tests/gitea-repositories-meta/user2/commits_search_test.git/objects/d6/ae8023a10ff446b6a4e7f441554834008e99c3
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/objects/d6/ae8023a10ff446b6a4e7f441554834008e99c3
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/objects/d6/ae8023a10ff446b6a4e7f441554834008e99c3
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/packed-refs b/tests/gitea-repositories-meta/user2/commits_search_test.git/packed-refs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/packed-refs
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/packed-refs
diff --git a/integrations/gitea-repositories-meta/user2/commits_search_test.git/refs/heads/master b/tests/gitea-repositories-meta/user2/commits_search_test.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/commits_search_test.git/refs/heads/master
rename to tests/gitea-repositories-meta/user2/commits_search_test.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/HEAD b/tests/gitea-repositories-meta/user2/git_hooks_test.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/HEAD
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/config b/tests/gitea-repositories-meta/user2/git_hooks_test.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/config
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/config
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/description b/tests/gitea-repositories-meta/user2/git_hooks_test.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/description
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/description
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/post-receive b/tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/post-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/post-receive
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/post-receive
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/post-receive.d/gitea b/tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/post-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/post-receive.d/gitea
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/post-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive b/tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive.d/gitea b/tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive.d/gitea
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive.d/pre-receive b/tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive.d/pre-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive.d/pre-receive
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/pre-receive.d/pre-receive
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/update b/tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/update
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/update
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/update
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/update.d/gitea b/tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/update.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/hooks/update.d/gitea
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/hooks/update.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/info/exclude b/tests/gitea-repositories-meta/user2/git_hooks_test.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/info/exclude
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/info/refs b/tests/gitea-repositories-meta/user2/git_hooks_test.git/info/refs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/info/refs
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/info/refs
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6 b/tests/gitea-repositories-meta/user2/git_hooks_test.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f b/tests/gitea-repositories-meta/user2/git_hooks_test.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d b/tests/gitea-repositories-meta/user2/git_hooks_test.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/objects/info/packs b/tests/gitea-repositories-meta/user2/git_hooks_test.git/objects/info/packs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/objects/info/packs
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/objects/info/packs
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/DefaultBranch b/tests/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/DefaultBranch
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/DefaultBranch
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/DefaultBranch
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/develop b/tests/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/develop
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/develop
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/develop
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/feature/1 b/tests/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/feature/1
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/feature/1
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/feature/1
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/master b/tests/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/master
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user2/git_hooks_test.git/refs/tags/v1.1 b/tests/gitea-repositories-meta/user2/git_hooks_test.git/refs/tags/v1.1
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/git_hooks_test.git/refs/tags/v1.1
rename to tests/gitea-repositories-meta/user2/git_hooks_test.git/refs/tags/v1.1
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/HEAD b/tests/gitea-repositories-meta/user2/glob.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/HEAD
rename to tests/gitea-repositories-meta/user2/glob.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/config b/tests/gitea-repositories-meta/user2/glob.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/config
rename to tests/gitea-repositories-meta/user2/glob.git/config
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/description b/tests/gitea-repositories-meta/user2/glob.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/description
rename to tests/gitea-repositories-meta/user2/glob.git/description
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/info/exclude b/tests/gitea-repositories-meta/user2/glob.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/info/exclude
rename to tests/gitea-repositories-meta/user2/glob.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/objects/48/06cb9df135782b818c968c2fadbd2c150d23d6 b/tests/gitea-repositories-meta/user2/glob.git/objects/48/06cb9df135782b818c968c2fadbd2c150d23d6
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/objects/48/06cb9df135782b818c968c2fadbd2c150d23d6
rename to tests/gitea-repositories-meta/user2/glob.git/objects/48/06cb9df135782b818c968c2fadbd2c150d23d6
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/objects/59/fee614e09d1f1cd1e15e4b2a7e9c8873a81498 b/tests/gitea-repositories-meta/user2/glob.git/objects/59/fee614e09d1f1cd1e15e4b2a7e9c8873a81498
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/objects/59/fee614e09d1f1cd1e15e4b2a7e9c8873a81498
rename to tests/gitea-repositories-meta/user2/glob.git/objects/59/fee614e09d1f1cd1e15e4b2a7e9c8873a81498
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/objects/7c/8ac2f8d82a1eb5f6aaece6629ff11015f91eb4 b/tests/gitea-repositories-meta/user2/glob.git/objects/7c/8ac2f8d82a1eb5f6aaece6629ff11015f91eb4
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/objects/7c/8ac2f8d82a1eb5f6aaece6629ff11015f91eb4
rename to tests/gitea-repositories-meta/user2/glob.git/objects/7c/8ac2f8d82a1eb5f6aaece6629ff11015f91eb4
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/objects/8e/592e636d27ac144f92f7fe8c33631cbdea594d b/tests/gitea-repositories-meta/user2/glob.git/objects/8e/592e636d27ac144f92f7fe8c33631cbdea594d
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/objects/8e/592e636d27ac144f92f7fe8c33631cbdea594d
rename to tests/gitea-repositories-meta/user2/glob.git/objects/8e/592e636d27ac144f92f7fe8c33631cbdea594d
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/objects/95/aff026f99a9ab76fbd01decb63dd3dbc03e498 b/tests/gitea-repositories-meta/user2/glob.git/objects/95/aff026f99a9ab76fbd01decb63dd3dbc03e498
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/objects/95/aff026f99a9ab76fbd01decb63dd3dbc03e498
rename to tests/gitea-repositories-meta/user2/glob.git/objects/95/aff026f99a9ab76fbd01decb63dd3dbc03e498
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/objects/ae/d1ffed24cc3cf9b80490795e893cae4bddd684 b/tests/gitea-repositories-meta/user2/glob.git/objects/ae/d1ffed24cc3cf9b80490795e893cae4bddd684
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/objects/ae/d1ffed24cc3cf9b80490795e893cae4bddd684
rename to tests/gitea-repositories-meta/user2/glob.git/objects/ae/d1ffed24cc3cf9b80490795e893cae4bddd684
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/objects/bf/d6a6583f9a9ac59bd726c1df26c64a89427ede b/tests/gitea-repositories-meta/user2/glob.git/objects/bf/d6a6583f9a9ac59bd726c1df26c64a89427ede
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/objects/bf/d6a6583f9a9ac59bd726c1df26c64a89427ede
rename to tests/gitea-repositories-meta/user2/glob.git/objects/bf/d6a6583f9a9ac59bd726c1df26c64a89427ede
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/objects/c8/eb3b6c767ccb68411d0a1f6c769be69fb4d95a b/tests/gitea-repositories-meta/user2/glob.git/objects/c8/eb3b6c767ccb68411d0a1f6c769be69fb4d95a
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/objects/c8/eb3b6c767ccb68411d0a1f6c769be69fb4d95a
rename to tests/gitea-repositories-meta/user2/glob.git/objects/c8/eb3b6c767ccb68411d0a1f6c769be69fb4d95a
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/objects/de/6be43fe8eb19ca3f4e934cb8b9a9a0b20fe865 b/tests/gitea-repositories-meta/user2/glob.git/objects/de/6be43fe8eb19ca3f4e934cb8b9a9a0b20fe865
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/objects/de/6be43fe8eb19ca3f4e934cb8b9a9a0b20fe865
rename to tests/gitea-repositories-meta/user2/glob.git/objects/de/6be43fe8eb19ca3f4e934cb8b9a9a0b20fe865
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/objects/ef/6b814b610d8e7717aa0f71fbe5842bcf814697 b/tests/gitea-repositories-meta/user2/glob.git/objects/ef/6b814b610d8e7717aa0f71fbe5842bcf814697
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/objects/ef/6b814b610d8e7717aa0f71fbe5842bcf814697
rename to tests/gitea-repositories-meta/user2/glob.git/objects/ef/6b814b610d8e7717aa0f71fbe5842bcf814697
diff --git a/integrations/gitea-repositories-meta/user2/glob.git/refs/heads/master b/tests/gitea-repositories-meta/user2/glob.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/glob.git/refs/heads/master
rename to tests/gitea-repositories-meta/user2/glob.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/HEAD b/tests/gitea-repositories-meta/user2/repo1.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/HEAD
rename to tests/gitea-repositories-meta/user2/repo1.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/config b/tests/gitea-repositories-meta/user2/repo1.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/config
rename to tests/gitea-repositories-meta/user2/repo1.git/config
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/description b/tests/gitea-repositories-meta/user2/repo1.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/description
rename to tests/gitea-repositories-meta/user2/repo1.git/description
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/post-receive b/tests/gitea-repositories-meta/user2/repo1.git/hooks/post-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/hooks/post-receive
rename to tests/gitea-repositories-meta/user2/repo1.git/hooks/post-receive
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/post-receive.d/gitea b/tests/gitea-repositories-meta/user2/repo1.git/hooks/post-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/hooks/post-receive.d/gitea
rename to tests/gitea-repositories-meta/user2/repo1.git/hooks/post-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive b/tests/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive
rename to tests/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive.d/gitea b/tests/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive.d/gitea
rename to tests/gitea-repositories-meta/user2/repo1.git/hooks/pre-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/update b/tests/gitea-repositories-meta/user2/repo1.git/hooks/update
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/hooks/update
rename to tests/gitea-repositories-meta/user2/repo1.git/hooks/update
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/hooks/update.d/gitea b/tests/gitea-repositories-meta/user2/repo1.git/hooks/update.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/hooks/update.d/gitea
rename to tests/gitea-repositories-meta/user2/repo1.git/hooks/update.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/info/exclude b/tests/gitea-repositories-meta/user2/repo1.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/info/exclude
rename to tests/gitea-repositories-meta/user2/repo1.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/info/refs b/tests/gitea-repositories-meta/user2/repo1.git/info/refs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/info/refs
rename to tests/gitea-repositories-meta/user2/repo1.git/info/refs
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/00/750edc07d6415dcc07ae0351e9397b0222b7ba b/tests/gitea-repositories-meta/user2/repo1.git/objects/00/750edc07d6415dcc07ae0351e9397b0222b7ba
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/00/750edc07d6415dcc07ae0351e9397b0222b7ba
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/00/750edc07d6415dcc07ae0351e9397b0222b7ba
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6 b/tests/gitea-repositories-meta/user2/repo1.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/2a/2f1d4670728a2e10049e345bd7a276468beab6
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/3f/a2f829675543ecfc16b2891aebe8bf0608a8f4 b/tests/gitea-repositories-meta/user2/repo1.git/objects/3f/a2f829675543ecfc16b2891aebe8bf0608a8f4
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/3f/a2f829675543ecfc16b2891aebe8bf0608a8f4
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/3f/a2f829675543ecfc16b2891aebe8bf0608a8f4
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/4a/357436d925b5c974181ff12a994538ddc5a269 b/tests/gitea-repositories-meta/user2/repo1.git/objects/4a/357436d925b5c974181ff12a994538ddc5a269
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/4a/357436d925b5c974181ff12a994538ddc5a269
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/4a/357436d925b5c974181ff12a994538ddc5a269
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f b/tests/gitea-repositories-meta/user2/repo1.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/4b/4851ad51df6a7d9f25c979345979eaeb5b349f
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/5c/050d3b6d2db231ab1f64e324f1b6b9a0b181c2 b/tests/gitea-repositories-meta/user2/repo1.git/objects/5c/050d3b6d2db231ab1f64e324f1b6b9a0b181c2
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/5c/050d3b6d2db231ab1f64e324f1b6b9a0b181c2
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/5c/050d3b6d2db231ab1f64e324f1b6b9a0b181c2
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/5f/22f7d0d95d614d25a5b68592adb345a4b5c7fd b/tests/gitea-repositories-meta/user2/repo1.git/objects/5f/22f7d0d95d614d25a5b68592adb345a4b5c7fd
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/5f/22f7d0d95d614d25a5b68592adb345a4b5c7fd
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/5f/22f7d0d95d614d25a5b68592adb345a4b5c7fd
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/62/fb502a7172d4453f0322a2cc85bddffa57f07a b/tests/gitea-repositories-meta/user2/repo1.git/objects/62/fb502a7172d4453f0322a2cc85bddffa57f07a
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/62/fb502a7172d4453f0322a2cc85bddffa57f07a
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/62/fb502a7172d4453f0322a2cc85bddffa57f07a
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d b/tests/gitea-repositories-meta/user2/repo1.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/65/f1bf27bc3bf70f64657658635e66094edbcb4d
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/6a/a3a5385611c5eb8986c9961a9c34a93cbaadfb b/tests/gitea-repositories-meta/user2/repo1.git/objects/6a/a3a5385611c5eb8986c9961a9c34a93cbaadfb
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/6a/a3a5385611c5eb8986c9961a9c34a93cbaadfb
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/6a/a3a5385611c5eb8986c9961a9c34a93cbaadfb
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/7c/4df115542e05c700f297519e906fd63c9c9804 b/tests/gitea-repositories-meta/user2/repo1.git/objects/7c/4df115542e05c700f297519e906fd63c9c9804
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/7c/4df115542e05c700f297519e906fd63c9c9804
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/7c/4df115542e05c700f297519e906fd63c9c9804
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/90/dcd07da077d1e7cd6032b52d1f79ae2b5f19b2 b/tests/gitea-repositories-meta/user2/repo1.git/objects/90/dcd07da077d1e7cd6032b52d1f79ae2b5f19b2
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/90/dcd07da077d1e7cd6032b52d1f79ae2b5f19b2
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/90/dcd07da077d1e7cd6032b52d1f79ae2b5f19b2
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/94/922e1295c678267de1193b7b84ad8a086c27f9 b/tests/gitea-repositories-meta/user2/repo1.git/objects/94/922e1295c678267de1193b7b84ad8a086c27f9
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/94/922e1295c678267de1193b7b84ad8a086c27f9
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/94/922e1295c678267de1193b7b84ad8a086c27f9
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/98/5f0301dba5e7b34be866819cd15ad3d8f508ee b/tests/gitea-repositories-meta/user2/repo1.git/objects/98/5f0301dba5e7b34be866819cd15ad3d8f508ee
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/98/5f0301dba5e7b34be866819cd15ad3d8f508ee
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/98/5f0301dba5e7b34be866819cd15ad3d8f508ee
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/a6/9277c81e90b98a7c0ab25b042a6e296da8eb9a b/tests/gitea-repositories-meta/user2/repo1.git/objects/a6/9277c81e90b98a7c0ab25b042a6e296da8eb9a
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/a6/9277c81e90b98a7c0ab25b042a6e296da8eb9a
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/a6/9277c81e90b98a7c0ab25b042a6e296da8eb9a
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/a7/57c0ea621e63d0fd6fc353a175fdc7199e5d1d b/tests/gitea-repositories-meta/user2/repo1.git/objects/a7/57c0ea621e63d0fd6fc353a175fdc7199e5d1d
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/a7/57c0ea621e63d0fd6fc353a175fdc7199e5d1d
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/a7/57c0ea621e63d0fd6fc353a175fdc7199e5d1d
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/b2/60587271671842af0b036e4fe643c9d45b7ddd b/tests/gitea-repositories-meta/user2/repo1.git/objects/b2/60587271671842af0b036e4fe643c9d45b7ddd
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/b2/60587271671842af0b036e4fe643c9d45b7ddd
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/b2/60587271671842af0b036e4fe643c9d45b7ddd
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/d4/a1a6dcf7bd42891f264d484e80dac7e66b5410 b/tests/gitea-repositories-meta/user2/repo1.git/objects/d4/a1a6dcf7bd42891f264d484e80dac7e66b5410
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/d4/a1a6dcf7bd42891f264d484e80dac7e66b5410
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/d4/a1a6dcf7bd42891f264d484e80dac7e66b5410
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/d7/bd5b8cfb680f460e37b6fd7cf74c284e059118 b/tests/gitea-repositories-meta/user2/repo1.git/objects/d7/bd5b8cfb680f460e37b6fd7cf74c284e059118
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/d7/bd5b8cfb680f460e37b6fd7cf74c284e059118
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/d7/bd5b8cfb680f460e37b6fd7cf74c284e059118
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/dc/7a8ba127fee870dd683310ce660dfe59333a1b b/tests/gitea-repositories-meta/user2/repo1.git/objects/dc/7a8ba127fee870dd683310ce660dfe59333a1b
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/dc/7a8ba127fee870dd683310ce660dfe59333a1b
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/dc/7a8ba127fee870dd683310ce660dfe59333a1b
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/dd/59742c0f6672911f2b64cba5711ac00593ed32 b/tests/gitea-repositories-meta/user2/repo1.git/objects/dd/59742c0f6672911f2b64cba5711ac00593ed32
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/dd/59742c0f6672911f2b64cba5711ac00593ed32
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/dd/59742c0f6672911f2b64cba5711ac00593ed32
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/info/packs b/tests/gitea-repositories-meta/user2/repo1.git/objects/info/packs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/objects/info/packs
rename to tests/gitea-repositories-meta/user2/repo1.git/objects/info/packs
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/DefaultBranch b/tests/gitea-repositories-meta/user2/repo1.git/refs/heads/DefaultBranch
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/DefaultBranch
rename to tests/gitea-repositories-meta/user2/repo1.git/refs/heads/DefaultBranch
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/branch2 b/tests/gitea-repositories-meta/user2/repo1.git/refs/heads/branch2
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/branch2
rename to tests/gitea-repositories-meta/user2/repo1.git/refs/heads/branch2
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/develop b/tests/gitea-repositories-meta/user2/repo1.git/refs/heads/develop
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/develop
rename to tests/gitea-repositories-meta/user2/repo1.git/refs/heads/develop
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/feature/1 b/tests/gitea-repositories-meta/user2/repo1.git/refs/heads/feature/1
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/feature/1
rename to tests/gitea-repositories-meta/user2/repo1.git/refs/heads/feature/1
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/master b/tests/gitea-repositories-meta/user2/repo1.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/master
rename to tests/gitea-repositories-meta/user2/repo1.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/pr-to-update b/tests/gitea-repositories-meta/user2/repo1.git/refs/heads/pr-to-update
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/refs/heads/pr-to-update
rename to tests/gitea-repositories-meta/user2/repo1.git/refs/heads/pr-to-update
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/notes/commits b/tests/gitea-repositories-meta/user2/repo1.git/refs/notes/commits
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/refs/notes/commits
rename to tests/gitea-repositories-meta/user2/repo1.git/refs/notes/commits
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/2/head b/tests/gitea-repositories-meta/user2/repo1.git/refs/pull/2/head
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/2/head
rename to tests/gitea-repositories-meta/user2/repo1.git/refs/pull/2/head
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/3/head b/tests/gitea-repositories-meta/user2/repo1.git/refs/pull/3/head
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/3/head
rename to tests/gitea-repositories-meta/user2/repo1.git/refs/pull/3/head
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/5/head b/tests/gitea-repositories-meta/user2/repo1.git/refs/pull/5/head
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/5/head
rename to tests/gitea-repositories-meta/user2/repo1.git/refs/pull/5/head
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/tags/v1.1 b/tests/gitea-repositories-meta/user2/repo1.git/refs/tags/v1.1
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.git/refs/tags/v1.1
rename to tests/gitea-repositories-meta/user2/repo1.git/refs/tags/v1.1
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/HEAD b/tests/gitea-repositories-meta/user2/repo1.wiki.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/HEAD
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/config b/tests/gitea-repositories-meta/user2/repo1.wiki.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/config
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/config
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/description b/tests/gitea-repositories-meta/user2/repo1.wiki.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/description
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/description
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/info/exclude b/tests/gitea-repositories-meta/user2/repo1.wiki.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/info/exclude
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/0c/f15c3f66ec8384480ed9c3cf87c9e97fbb0ec3 b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/0c/f15c3f66ec8384480ed9c3cf87c9e97fbb0ec3
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/0c/f15c3f66ec8384480ed9c3cf87c9e97fbb0ec3
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/0c/f15c3f66ec8384480ed9c3cf87c9e97fbb0ec3
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/0d/ca5bd9b5d7ef937710e056f575e86c0184ba85 b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/0d/ca5bd9b5d7ef937710e056f575e86c0184ba85
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/0d/ca5bd9b5d7ef937710e056f575e86c0184ba85
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/0d/ca5bd9b5d7ef937710e056f575e86c0184ba85
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/2c/54faec6c45d31c1abfaecdab471eac6633738a b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/2c/54faec6c45d31c1abfaecdab471eac6633738a
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/2c/54faec6c45d31c1abfaecdab471eac6633738a
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/2c/54faec6c45d31c1abfaecdab471eac6633738a
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/32/5dc4f8e9344e6668f21536a69d5f1d4ed53ca3 b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/32/5dc4f8e9344e6668f21536a69d5f1d4ed53ca3
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/32/5dc4f8e9344e6668f21536a69d5f1d4ed53ca3
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/32/5dc4f8e9344e6668f21536a69d5f1d4ed53ca3
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/42/3313fbd38093bb10d0c8387db9105409c6f196 b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/42/3313fbd38093bb10d0c8387db9105409c6f196
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/42/3313fbd38093bb10d0c8387db9105409c6f196
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/42/3313fbd38093bb10d0c8387db9105409c6f196
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/71/911bf48766c7181518c1070911019fbb00b1fc b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/71/911bf48766c7181518c1070911019fbb00b1fc
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/71/911bf48766c7181518c1070911019fbb00b1fc
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/71/911bf48766c7181518c1070911019fbb00b1fc
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/72/fc6251cc648e914c10009d31431fa2e38b9a20 b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/72/fc6251cc648e914c10009d31431fa2e38b9a20
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/72/fc6251cc648e914c10009d31431fa2e38b9a20
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/72/fc6251cc648e914c10009d31431fa2e38b9a20
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/74/d5a0d73db9b9ef7aa9978eb7a099b08f54d45e b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/74/d5a0d73db9b9ef7aa9978eb7a099b08f54d45e
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/74/d5a0d73db9b9ef7aa9978eb7a099b08f54d45e
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/74/d5a0d73db9b9ef7aa9978eb7a099b08f54d45e
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/7c/d7c8fa852973c72c66eb120a6677c54a8697f7 b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/7c/d7c8fa852973c72c66eb120a6677c54a8697f7
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/7c/d7c8fa852973c72c66eb120a6677c54a8697f7
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/7c/d7c8fa852973c72c66eb120a6677c54a8697f7
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/89/43a1d5f93c00439d5ffc0f8e36f5d60abae46c b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/89/43a1d5f93c00439d5ffc0f8e36f5d60abae46c
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/89/43a1d5f93c00439d5ffc0f8e36f5d60abae46c
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/89/43a1d5f93c00439d5ffc0f8e36f5d60abae46c
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/c1/0d10b7e655b3dab1f53176db57c8219a5488d6 b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/c1/0d10b7e655b3dab1f53176db57c8219a5488d6
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/c1/0d10b7e655b3dab1f53176db57c8219a5488d6
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/c1/0d10b7e655b3dab1f53176db57c8219a5488d6
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/c4/b38c3e1395393f75bbbc2ed10c7eeb577d3b64 b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/c4/b38c3e1395393f75bbbc2ed10c7eeb577d3b64
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/c4/b38c3e1395393f75bbbc2ed10c7eeb577d3b64
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/c4/b38c3e1395393f75bbbc2ed10c7eeb577d3b64
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/e5/3d079e581fbfdea1075a54d5b621eab0090e52 b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/e5/3d079e581fbfdea1075a54d5b621eab0090e52
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/e5/3d079e581fbfdea1075a54d5b621eab0090e52
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/e5/3d079e581fbfdea1075a54d5b621eab0090e52
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/ea/82fc8777a24b07c26b3a4bf4e2742c03733eab b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/ea/82fc8777a24b07c26b3a4bf4e2742c03733eab
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/ea/82fc8777a24b07c26b3a4bf4e2742c03733eab
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/ea/82fc8777a24b07c26b3a4bf4e2742c03733eab
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/f5/05ec9b5c7a45a10259c1dda7f18434e5d55940 b/tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/f5/05ec9b5c7a45a10259c1dda7f18434e5d55940
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/f5/05ec9b5c7a45a10259c1dda7f18434e5d55940
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/objects/f5/05ec9b5c7a45a10259c1dda7f18434e5d55940
diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master b/tests/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master
rename to tests/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/HEAD b/tests/gitea-repositories-meta/user2/repo15.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo15.git/HEAD
rename to tests/gitea-repositories-meta/user2/repo15.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/config b/tests/gitea-repositories-meta/user2/repo15.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo15.git/config
rename to tests/gitea-repositories-meta/user2/repo15.git/config
diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/description b/tests/gitea-repositories-meta/user2/repo15.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo15.git/description
rename to tests/gitea-repositories-meta/user2/repo15.git/description
diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/post-receive b/tests/gitea-repositories-meta/user2/repo15.git/hooks/post-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo15.git/hooks/post-receive
rename to tests/gitea-repositories-meta/user2/repo15.git/hooks/post-receive
diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/post-receive.d/gitea b/tests/gitea-repositories-meta/user2/repo15.git/hooks/post-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo15.git/hooks/post-receive.d/gitea
rename to tests/gitea-repositories-meta/user2/repo15.git/hooks/post-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive b/tests/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive
rename to tests/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive
diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive.d/gitea b/tests/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive.d/gitea
rename to tests/gitea-repositories-meta/user2/repo15.git/hooks/pre-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/update b/tests/gitea-repositories-meta/user2/repo15.git/hooks/update
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo15.git/hooks/update
rename to tests/gitea-repositories-meta/user2/repo15.git/hooks/update
diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/hooks/update.d/gitea b/tests/gitea-repositories-meta/user2/repo15.git/hooks/update.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo15.git/hooks/update.d/gitea
rename to tests/gitea-repositories-meta/user2/repo15.git/hooks/update.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/repo15.git/info/exclude b/tests/gitea-repositories-meta/user2/repo15.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo15.git/info/exclude
rename to tests/gitea-repositories-meta/user2/repo15.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/HEAD b/tests/gitea-repositories-meta/user2/repo16.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/HEAD
rename to tests/gitea-repositories-meta/user2/repo16.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/config b/tests/gitea-repositories-meta/user2/repo16.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/config
rename to tests/gitea-repositories-meta/user2/repo16.git/config
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/description b/tests/gitea-repositories-meta/user2/repo16.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/description
rename to tests/gitea-repositories-meta/user2/repo16.git/description
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/info/exclude b/tests/gitea-repositories-meta/user2/repo16.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/info/exclude
rename to tests/gitea-repositories-meta/user2/repo16.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/objects/0c/3d59dea27b97aa3cb66072745d7a2c51a7a8b1 b/tests/gitea-repositories-meta/user2/repo16.git/objects/0c/3d59dea27b97aa3cb66072745d7a2c51a7a8b1
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/objects/0c/3d59dea27b97aa3cb66072745d7a2c51a7a8b1
rename to tests/gitea-repositories-meta/user2/repo16.git/objects/0c/3d59dea27b97aa3cb66072745d7a2c51a7a8b1
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/objects/24/f83a471f77579fea57bac7255d6e64e70fce1c b/tests/gitea-repositories-meta/user2/repo16.git/objects/24/f83a471f77579fea57bac7255d6e64e70fce1c
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/objects/24/f83a471f77579fea57bac7255d6e64e70fce1c
rename to tests/gitea-repositories-meta/user2/repo16.git/objects/24/f83a471f77579fea57bac7255d6e64e70fce1c
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/objects/27/566bd5738fc8b4e3fef3c5e72cce608537bd95 b/tests/gitea-repositories-meta/user2/repo16.git/objects/27/566bd5738fc8b4e3fef3c5e72cce608537bd95
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/objects/27/566bd5738fc8b4e3fef3c5e72cce608537bd95
rename to tests/gitea-repositories-meta/user2/repo16.git/objects/27/566bd5738fc8b4e3fef3c5e72cce608537bd95
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/objects/3b/2b54fe3d9a8279d5b926124dccdf279b8eff2f b/tests/gitea-repositories-meta/user2/repo16.git/objects/3b/2b54fe3d9a8279d5b926124dccdf279b8eff2f
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/objects/3b/2b54fe3d9a8279d5b926124dccdf279b8eff2f
rename to tests/gitea-repositories-meta/user2/repo16.git/objects/3b/2b54fe3d9a8279d5b926124dccdf279b8eff2f
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/objects/45/8121ce9a6b855c9733bae62093caf3f39685de b/tests/gitea-repositories-meta/user2/repo16.git/objects/45/8121ce9a6b855c9733bae62093caf3f39685de
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/objects/45/8121ce9a6b855c9733bae62093caf3f39685de
rename to tests/gitea-repositories-meta/user2/repo16.git/objects/45/8121ce9a6b855c9733bae62093caf3f39685de
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/objects/50/99b81332712fe655e34e8dd63574f503f61811 b/tests/gitea-repositories-meta/user2/repo16.git/objects/50/99b81332712fe655e34e8dd63574f503f61811
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/objects/50/99b81332712fe655e34e8dd63574f503f61811
rename to tests/gitea-repositories-meta/user2/repo16.git/objects/50/99b81332712fe655e34e8dd63574f503f61811
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/objects/69/554a64c1e6030f051e5c3f94bfbd773cd6a324 b/tests/gitea-repositories-meta/user2/repo16.git/objects/69/554a64c1e6030f051e5c3f94bfbd773cd6a324
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/objects/69/554a64c1e6030f051e5c3f94bfbd773cd6a324
rename to tests/gitea-repositories-meta/user2/repo16.git/objects/69/554a64c1e6030f051e5c3f94bfbd773cd6a324
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/objects/a4/3476a501516e065c5a82f05fd58fd319598bc1 b/tests/gitea-repositories-meta/user2/repo16.git/objects/a4/3476a501516e065c5a82f05fd58fd319598bc1
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/objects/a4/3476a501516e065c5a82f05fd58fd319598bc1
rename to tests/gitea-repositories-meta/user2/repo16.git/objects/a4/3476a501516e065c5a82f05fd58fd319598bc1
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/objects/e9/4083fcdf1f10c545e9253a23c5e44a2ff68aac b/tests/gitea-repositories-meta/user2/repo16.git/objects/e9/4083fcdf1f10c545e9253a23c5e44a2ff68aac
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/objects/e9/4083fcdf1f10c545e9253a23c5e44a2ff68aac
rename to tests/gitea-repositories-meta/user2/repo16.git/objects/e9/4083fcdf1f10c545e9253a23c5e44a2ff68aac
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/objects/f2/7c2b2b03dcab38beaf89b0ab4ff61f6de63441 b/tests/gitea-repositories-meta/user2/repo16.git/objects/f2/7c2b2b03dcab38beaf89b0ab4ff61f6de63441
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/objects/f2/7c2b2b03dcab38beaf89b0ab4ff61f6de63441
rename to tests/gitea-repositories-meta/user2/repo16.git/objects/f2/7c2b2b03dcab38beaf89b0ab4ff61f6de63441
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/objects/f9/0451c72ef61a7645293d17b47be7a8e983da57 b/tests/gitea-repositories-meta/user2/repo16.git/objects/f9/0451c72ef61a7645293d17b47be7a8e983da57
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/objects/f9/0451c72ef61a7645293d17b47be7a8e983da57
rename to tests/gitea-repositories-meta/user2/repo16.git/objects/f9/0451c72ef61a7645293d17b47be7a8e983da57
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/refs/heads/good-sign b/tests/gitea-repositories-meta/user2/repo16.git/refs/heads/good-sign
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/refs/heads/good-sign
rename to tests/gitea-repositories-meta/user2/repo16.git/refs/heads/good-sign
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/refs/heads/good-sign-not-yet-validated b/tests/gitea-repositories-meta/user2/repo16.git/refs/heads/good-sign-not-yet-validated
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/refs/heads/good-sign-not-yet-validated
rename to tests/gitea-repositories-meta/user2/repo16.git/refs/heads/good-sign-not-yet-validated
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/refs/heads/master b/tests/gitea-repositories-meta/user2/repo16.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/refs/heads/master
rename to tests/gitea-repositories-meta/user2/repo16.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user2/repo16.git/refs/heads/not-signed b/tests/gitea-repositories-meta/user2/repo16.git/refs/heads/not-signed
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo16.git/refs/heads/not-signed
rename to tests/gitea-repositories-meta/user2/repo16.git/refs/heads/not-signed
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/HEAD b/tests/gitea-repositories-meta/user2/repo2.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/HEAD
rename to tests/gitea-repositories-meta/user2/repo2.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/config b/tests/gitea-repositories-meta/user2/repo2.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/config
rename to tests/gitea-repositories-meta/user2/repo2.git/config
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/description b/tests/gitea-repositories-meta/user2/repo2.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/description
rename to tests/gitea-repositories-meta/user2/repo2.git/description
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/info/exclude b/tests/gitea-repositories-meta/user2/repo2.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/info/exclude
rename to tests/gitea-repositories-meta/user2/repo2.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/info/refs b/tests/gitea-repositories-meta/user2/repo2.git/info/refs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/info/refs
rename to tests/gitea-repositories-meta/user2/repo2.git/info/refs
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/0a/7d8b41ae9763e9a1743917396839d1791d49d0 b/tests/gitea-repositories-meta/user2/repo2.git/objects/0a/7d8b41ae9763e9a1743917396839d1791d49d0
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/0a/7d8b41ae9763e9a1743917396839d1791d49d0
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/0a/7d8b41ae9763e9a1743917396839d1791d49d0
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/0c/f15c3f66ec8384480ed9c3cf87c9e97fbb0ec3 b/tests/gitea-repositories-meta/user2/repo2.git/objects/0c/f15c3f66ec8384480ed9c3cf87c9e97fbb0ec3
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/0c/f15c3f66ec8384480ed9c3cf87c9e97fbb0ec3
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/0c/f15c3f66ec8384480ed9c3cf87c9e97fbb0ec3
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/10/32bbf17fbc0d9c95bb5418dabe8f8c99278700 b/tests/gitea-repositories-meta/user2/repo2.git/objects/10/32bbf17fbc0d9c95bb5418dabe8f8c99278700
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/10/32bbf17fbc0d9c95bb5418dabe8f8c99278700
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/10/32bbf17fbc0d9c95bb5418dabe8f8c99278700
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/1c/887eaa8d81fa86da7695d8f635cf17813eb422 b/tests/gitea-repositories-meta/user2/repo2.git/objects/1c/887eaa8d81fa86da7695d8f635cf17813eb422
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/1c/887eaa8d81fa86da7695d8f635cf17813eb422
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/1c/887eaa8d81fa86da7695d8f635cf17813eb422
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/26/f842bcad37fa40a1bb34cbb5ee219ee35d863d b/tests/gitea-repositories-meta/user2/repo2.git/objects/26/f842bcad37fa40a1bb34cbb5ee219ee35d863d
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/26/f842bcad37fa40a1bb34cbb5ee219ee35d863d
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/26/f842bcad37fa40a1bb34cbb5ee219ee35d863d
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/32/5dc4f8e9344e6668f21536a69d5f1d4ed53ca3 b/tests/gitea-repositories-meta/user2/repo2.git/objects/32/5dc4f8e9344e6668f21536a69d5f1d4ed53ca3
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/32/5dc4f8e9344e6668f21536a69d5f1d4ed53ca3
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/32/5dc4f8e9344e6668f21536a69d5f1d4ed53ca3
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/36/fff01c8c9f722d49d53186abd27b5be8d85338 b/tests/gitea-repositories-meta/user2/repo2.git/objects/36/fff01c8c9f722d49d53186abd27b5be8d85338
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/36/fff01c8c9f722d49d53186abd27b5be8d85338
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/36/fff01c8c9f722d49d53186abd27b5be8d85338
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/42/3313fbd38093bb10d0c8387db9105409c6f196 b/tests/gitea-repositories-meta/user2/repo2.git/objects/42/3313fbd38093bb10d0c8387db9105409c6f196
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/42/3313fbd38093bb10d0c8387db9105409c6f196
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/42/3313fbd38093bb10d0c8387db9105409c6f196
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/71/911bf48766c7181518c1070911019fbb00b1fc b/tests/gitea-repositories-meta/user2/repo2.git/objects/71/911bf48766c7181518c1070911019fbb00b1fc
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/71/911bf48766c7181518c1070911019fbb00b1fc
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/71/911bf48766c7181518c1070911019fbb00b1fc
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/72/fc6251cc648e914c10009d31431fa2e38b9a20 b/tests/gitea-repositories-meta/user2/repo2.git/objects/72/fc6251cc648e914c10009d31431fa2e38b9a20
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/72/fc6251cc648e914c10009d31431fa2e38b9a20
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/72/fc6251cc648e914c10009d31431fa2e38b9a20
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/74/d5a0d73db9b9ef7aa9978eb7a099b08f54d45e b/tests/gitea-repositories-meta/user2/repo2.git/objects/74/d5a0d73db9b9ef7aa9978eb7a099b08f54d45e
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/74/d5a0d73db9b9ef7aa9978eb7a099b08f54d45e
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/74/d5a0d73db9b9ef7aa9978eb7a099b08f54d45e
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/7c/d7c8fa852973c72c66eb120a6677c54a8697f7 b/tests/gitea-repositories-meta/user2/repo2.git/objects/7c/d7c8fa852973c72c66eb120a6677c54a8697f7
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/7c/d7c8fa852973c72c66eb120a6677c54a8697f7
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/7c/d7c8fa852973c72c66eb120a6677c54a8697f7
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/ba/1aed4e2ea2443d76cec241b96be4ec990852ec b/tests/gitea-repositories-meta/user2/repo2.git/objects/ba/1aed4e2ea2443d76cec241b96be4ec990852ec
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/ba/1aed4e2ea2443d76cec241b96be4ec990852ec
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/ba/1aed4e2ea2443d76cec241b96be4ec990852ec
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/c1/0d10b7e655b3dab1f53176db57c8219a5488d6 b/tests/gitea-repositories-meta/user2/repo2.git/objects/c1/0d10b7e655b3dab1f53176db57c8219a5488d6
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/c1/0d10b7e655b3dab1f53176db57c8219a5488d6
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/c1/0d10b7e655b3dab1f53176db57c8219a5488d6
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/c4/b38c3e1395393f75bbbc2ed10c7eeb577d3b64 b/tests/gitea-repositories-meta/user2/repo2.git/objects/c4/b38c3e1395393f75bbbc2ed10c7eeb577d3b64
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/c4/b38c3e1395393f75bbbc2ed10c7eeb577d3b64
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/c4/b38c3e1395393f75bbbc2ed10c7eeb577d3b64
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/f5/05ec9b5c7a45a10259c1dda7f18434e5d55940 b/tests/gitea-repositories-meta/user2/repo2.git/objects/f5/05ec9b5c7a45a10259c1dda7f18434e5d55940
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/f5/05ec9b5c7a45a10259c1dda7f18434e5d55940
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/f5/05ec9b5c7a45a10259c1dda7f18434e5d55940
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/info/commit-graph b/tests/gitea-repositories-meta/user2/repo2.git/objects/info/commit-graph
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/info/commit-graph
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/info/commit-graph
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/info/packs b/tests/gitea-repositories-meta/user2/repo2.git/objects/info/packs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/info/packs
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/info/packs
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.bitmap b/tests/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.bitmap
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.bitmap
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.bitmap
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.idx b/tests/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.idx
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.idx
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.idx
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.pack b/tests/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.pack
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.pack
rename to tests/gitea-repositories-meta/user2/repo2.git/objects/pack/pack-a2f7ad943b3d857eb3ebdb4b35eeef38f63cf5d2.pack
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/packed-refs b/tests/gitea-repositories-meta/user2/repo2.git/packed-refs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/packed-refs
rename to tests/gitea-repositories-meta/user2/repo2.git/packed-refs
diff --git a/integrations/gitea-repositories-meta/user2/repo2.git/refs/heads/master b/tests/gitea-repositories-meta/user2/repo2.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo2.git/refs/heads/master
rename to tests/gitea-repositories-meta/user2/repo2.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/HEAD b/tests/gitea-repositories-meta/user2/repo20.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/HEAD
rename to tests/gitea-repositories-meta/user2/repo20.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/config b/tests/gitea-repositories-meta/user2/repo20.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/config
rename to tests/gitea-repositories-meta/user2/repo20.git/config
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/description b/tests/gitea-repositories-meta/user2/repo20.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/description
rename to tests/gitea-repositories-meta/user2/repo20.git/description
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/hooks/post-receive b/tests/gitea-repositories-meta/user2/repo20.git/hooks/post-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/hooks/post-receive
rename to tests/gitea-repositories-meta/user2/repo20.git/hooks/post-receive
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/hooks/post-receive.d/gitea b/tests/gitea-repositories-meta/user2/repo20.git/hooks/post-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/hooks/post-receive.d/gitea
rename to tests/gitea-repositories-meta/user2/repo20.git/hooks/post-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/hooks/pre-receive b/tests/gitea-repositories-meta/user2/repo20.git/hooks/pre-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/hooks/pre-receive
rename to tests/gitea-repositories-meta/user2/repo20.git/hooks/pre-receive
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/hooks/pre-receive.d/gitea b/tests/gitea-repositories-meta/user2/repo20.git/hooks/pre-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/hooks/pre-receive.d/gitea
rename to tests/gitea-repositories-meta/user2/repo20.git/hooks/pre-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/hooks/update b/tests/gitea-repositories-meta/user2/repo20.git/hooks/update
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/hooks/update
rename to tests/gitea-repositories-meta/user2/repo20.git/hooks/update
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/hooks/update.d/gitea b/tests/gitea-repositories-meta/user2/repo20.git/hooks/update.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/hooks/update.d/gitea
rename to tests/gitea-repositories-meta/user2/repo20.git/hooks/update.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/info/exclude b/tests/gitea-repositories-meta/user2/repo20.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/info/exclude
rename to tests/gitea-repositories-meta/user2/repo20.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/info/refs b/tests/gitea-repositories-meta/user2/repo20.git/info/refs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/info/refs
rename to tests/gitea-repositories-meta/user2/repo20.git/info/refs
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/02/15cbe13d2695a2c3464ab5e59f47f37c3ff5d5 b/tests/gitea-repositories-meta/user2/repo20.git/objects/02/15cbe13d2695a2c3464ab5e59f47f37c3ff5d5
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/02/15cbe13d2695a2c3464ab5e59f47f37c3ff5d5
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/02/15cbe13d2695a2c3464ab5e59f47f37c3ff5d5
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/05/81d7edf45206787ff93956ea892e8a2ae77604 b/tests/gitea-repositories-meta/user2/repo20.git/objects/05/81d7edf45206787ff93956ea892e8a2ae77604
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/05/81d7edf45206787ff93956ea892e8a2ae77604
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/05/81d7edf45206787ff93956ea892e8a2ae77604
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/1b/271d83842d348b1ee71d8e6ead400aaeb4d1b5 b/tests/gitea-repositories-meta/user2/repo20.git/objects/1b/271d83842d348b1ee71d8e6ead400aaeb4d1b5
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/1b/271d83842d348b1ee71d8e6ead400aaeb4d1b5
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/1b/271d83842d348b1ee71d8e6ead400aaeb4d1b5
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/29/5ba6ac57fdd46f62a51272f40e60b6dea697b2 b/tests/gitea-repositories-meta/user2/repo20.git/objects/29/5ba6ac57fdd46f62a51272f40e60b6dea697b2
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/29/5ba6ac57fdd46f62a51272f40e60b6dea697b2
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/29/5ba6ac57fdd46f62a51272f40e60b6dea697b2
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/2c/ec0f7069ed09d934e904c49f414d8bdf818ce4 b/tests/gitea-repositories-meta/user2/repo20.git/objects/2c/ec0f7069ed09d934e904c49f414d8bdf818ce4
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/2c/ec0f7069ed09d934e904c49f414d8bdf818ce4
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/2c/ec0f7069ed09d934e904c49f414d8bdf818ce4
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/41/4a282859758ba7b159bfbd9c2b193eb8f135ee b/tests/gitea-repositories-meta/user2/repo20.git/objects/41/4a282859758ba7b159bfbd9c2b193eb8f135ee
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/41/4a282859758ba7b159bfbd9c2b193eb8f135ee
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/41/4a282859758ba7b159bfbd9c2b193eb8f135ee
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/80/8038d2f71b0ab020991439cffd24309c7bc530 b/tests/gitea-repositories-meta/user2/repo20.git/objects/80/8038d2f71b0ab020991439cffd24309c7bc530
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/80/8038d2f71b0ab020991439cffd24309c7bc530
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/80/8038d2f71b0ab020991439cffd24309c7bc530
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/83/70977f63979e140b6b58992b1fdb4098b24cd9 b/tests/gitea-repositories-meta/user2/repo20.git/objects/83/70977f63979e140b6b58992b1fdb4098b24cd9
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/83/70977f63979e140b6b58992b1fdb4098b24cd9
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/83/70977f63979e140b6b58992b1fdb4098b24cd9
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/8c/e1dee41e1a3700819a9a309f275f8dc7b7e0b6 b/tests/gitea-repositories-meta/user2/repo20.git/objects/8c/e1dee41e1a3700819a9a309f275f8dc7b7e0b6
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/8c/e1dee41e1a3700819a9a309f275f8dc7b7e0b6
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/8c/e1dee41e1a3700819a9a309f275f8dc7b7e0b6
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/ba/3aeafe10402c6b29535a58d91def7e43638d9d b/tests/gitea-repositories-meta/user2/repo20.git/objects/ba/3aeafe10402c6b29535a58d91def7e43638d9d
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/ba/3aeafe10402c6b29535a58d91def7e43638d9d
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/ba/3aeafe10402c6b29535a58d91def7e43638d9d
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/c5/0ac6b9e25abb8200bb377755367d7265c581cf b/tests/gitea-repositories-meta/user2/repo20.git/objects/c5/0ac6b9e25abb8200bb377755367d7265c581cf
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/c5/0ac6b9e25abb8200bb377755367d7265c581cf
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/c5/0ac6b9e25abb8200bb377755367d7265c581cf
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a b/tests/gitea-repositories-meta/user2/repo20.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/db/89c972fc57862eae378f45b74aca228037d415 b/tests/gitea-repositories-meta/user2/repo20.git/objects/db/89c972fc57862eae378f45b74aca228037d415
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/db/89c972fc57862eae378f45b74aca228037d415
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/db/89c972fc57862eae378f45b74aca228037d415
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/objects/info/packs b/tests/gitea-repositories-meta/user2/repo20.git/objects/info/packs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/objects/info/packs
rename to tests/gitea-repositories-meta/user2/repo20.git/objects/info/packs
diff --git a/integrations/gitea-repositories-meta/user2/repo20.git/refs/heads/master b/tests/gitea-repositories-meta/user2/repo20.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/repo20.git/refs/heads/master
rename to tests/gitea-repositories-meta/user2/repo20.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/HEAD b/tests/gitea-repositories-meta/user2/utf8.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/HEAD
rename to tests/gitea-repositories-meta/user2/utf8.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/config b/tests/gitea-repositories-meta/user2/utf8.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/config
rename to tests/gitea-repositories-meta/user2/utf8.git/config
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/description b/tests/gitea-repositories-meta/user2/utf8.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/description
rename to tests/gitea-repositories-meta/user2/utf8.git/description
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/hooks/post-receive b/tests/gitea-repositories-meta/user2/utf8.git/hooks/post-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/hooks/post-receive
rename to tests/gitea-repositories-meta/user2/utf8.git/hooks/post-receive
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/hooks/post-receive.d/gitea b/tests/gitea-repositories-meta/user2/utf8.git/hooks/post-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/hooks/post-receive.d/gitea
rename to tests/gitea-repositories-meta/user2/utf8.git/hooks/post-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/hooks/pre-receive b/tests/gitea-repositories-meta/user2/utf8.git/hooks/pre-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/hooks/pre-receive
rename to tests/gitea-repositories-meta/user2/utf8.git/hooks/pre-receive
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/hooks/pre-receive.d/gitea b/tests/gitea-repositories-meta/user2/utf8.git/hooks/pre-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/hooks/pre-receive.d/gitea
rename to tests/gitea-repositories-meta/user2/utf8.git/hooks/pre-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/hooks/update b/tests/gitea-repositories-meta/user2/utf8.git/hooks/update
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/hooks/update
rename to tests/gitea-repositories-meta/user2/utf8.git/hooks/update
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/hooks/update.d/gitea b/tests/gitea-repositories-meta/user2/utf8.git/hooks/update.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/hooks/update.d/gitea
rename to tests/gitea-repositories-meta/user2/utf8.git/hooks/update.d/gitea
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/info/exclude b/tests/gitea-repositories-meta/user2/utf8.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/info/exclude
rename to tests/gitea-repositories-meta/user2/utf8.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/info/refs b/tests/gitea-repositories-meta/user2/utf8.git/info/refs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/info/refs
rename to tests/gitea-repositories-meta/user2/utf8.git/info/refs
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/14/c42687126acae9d1ad41d7bdb528f811065a6a b/tests/gitea-repositories-meta/user2/utf8.git/objects/14/c42687126acae9d1ad41d7bdb528f811065a6a
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/14/c42687126acae9d1ad41d7bdb528f811065a6a
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/14/c42687126acae9d1ad41d7bdb528f811065a6a
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/1d/5e00f305a7ca6a8a94e65456820a6d260adab8 b/tests/gitea-repositories-meta/user2/utf8.git/objects/1d/5e00f305a7ca6a8a94e65456820a6d260adab8
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/1d/5e00f305a7ca6a8a94e65456820a6d260adab8
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/1d/5e00f305a7ca6a8a94e65456820a6d260adab8
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/28/d579e4920fbf4f66e71dab3e779d9fbf41422a b/tests/gitea-repositories-meta/user2/utf8.git/objects/28/d579e4920fbf4f66e71dab3e779d9fbf41422a
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/28/d579e4920fbf4f66e71dab3e779d9fbf41422a
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/28/d579e4920fbf4f66e71dab3e779d9fbf41422a
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/3a/810dbf6b96afaa8c5f69a8b6ec1dabfca7368b b/tests/gitea-repositories-meta/user2/utf8.git/objects/3a/810dbf6b96afaa8c5f69a8b6ec1dabfca7368b
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/3a/810dbf6b96afaa8c5f69a8b6ec1dabfca7368b
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/3a/810dbf6b96afaa8c5f69a8b6ec1dabfca7368b
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/3a/a73c3499bff049a352b4e265575373e964b89a b/tests/gitea-repositories-meta/user2/utf8.git/objects/3a/a73c3499bff049a352b4e265575373e964b89a
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/3a/a73c3499bff049a352b4e265575373e964b89a
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/3a/a73c3499bff049a352b4e265575373e964b89a
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/3a/c6084110205f98174c4f1ec7e78cb21a15dfc2 b/tests/gitea-repositories-meta/user2/utf8.git/objects/3a/c6084110205f98174c4f1ec7e78cb21a15dfc2
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/3a/c6084110205f98174c4f1ec7e78cb21a15dfc2
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/3a/c6084110205f98174c4f1ec7e78cb21a15dfc2
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/4c/61dd0a799e0830e77edfe6c74f7c349bc8e62a b/tests/gitea-repositories-meta/user2/utf8.git/objects/4c/61dd0a799e0830e77edfe6c74f7c349bc8e62a
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/4c/61dd0a799e0830e77edfe6c74f7c349bc8e62a
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/4c/61dd0a799e0830e77edfe6c74f7c349bc8e62a
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/50/4d9fe743979d4e9785a25a363c7007293f0838 b/tests/gitea-repositories-meta/user2/utf8.git/objects/50/4d9fe743979d4e9785a25a363c7007293f0838
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/50/4d9fe743979d4e9785a25a363c7007293f0838
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/50/4d9fe743979d4e9785a25a363c7007293f0838
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/56/92bcf9f7c9eacb1ad68442161f2573877f96f4 b/tests/gitea-repositories-meta/user2/utf8.git/objects/56/92bcf9f7c9eacb1ad68442161f2573877f96f4
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/56/92bcf9f7c9eacb1ad68442161f2573877f96f4
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/56/92bcf9f7c9eacb1ad68442161f2573877f96f4
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/59/e2c41e8f5140bb0182acebec17c8ad9831cc62 b/tests/gitea-repositories-meta/user2/utf8.git/objects/59/e2c41e8f5140bb0182acebec17c8ad9831cc62
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/59/e2c41e8f5140bb0182acebec17c8ad9831cc62
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/59/e2c41e8f5140bb0182acebec17c8ad9831cc62
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/64/89894ad11093fdc49c0ed857d80682344a7264 b/tests/gitea-repositories-meta/user2/utf8.git/objects/64/89894ad11093fdc49c0ed857d80682344a7264
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/64/89894ad11093fdc49c0ed857d80682344a7264
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/64/89894ad11093fdc49c0ed857d80682344a7264
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/6d/0c79ce3401c67d1ad522e61c47083a9fdee16c b/tests/gitea-repositories-meta/user2/utf8.git/objects/6d/0c79ce3401c67d1ad522e61c47083a9fdee16c
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/6d/0c79ce3401c67d1ad522e61c47083a9fdee16c
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/6d/0c79ce3401c67d1ad522e61c47083a9fdee16c
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/84/7c6d93c6860dd377651245711b7fbcd34a18d4 b/tests/gitea-repositories-meta/user2/utf8.git/objects/84/7c6d93c6860dd377651245711b7fbcd34a18d4
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/84/7c6d93c6860dd377651245711b7fbcd34a18d4
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/84/7c6d93c6860dd377651245711b7fbcd34a18d4
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/9b/9cc8f558d1c4f815592496fa24308ba2a9c824 b/tests/gitea-repositories-meta/user2/utf8.git/objects/9b/9cc8f558d1c4f815592496fa24308ba2a9c824
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/9b/9cc8f558d1c4f815592496fa24308ba2a9c824
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/9b/9cc8f558d1c4f815592496fa24308ba2a9c824
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/a4/f1bb3f2f8c6a0e840e935812ef4903ce515dad b/tests/gitea-repositories-meta/user2/utf8.git/objects/a4/f1bb3f2f8c6a0e840e935812ef4903ce515dad
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/a4/f1bb3f2f8c6a0e840e935812ef4903ce515dad
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/a4/f1bb3f2f8c6a0e840e935812ef4903ce515dad
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/a9/a61830fbf4e84999d3b20cf178954366701fe5 b/tests/gitea-repositories-meta/user2/utf8.git/objects/a9/a61830fbf4e84999d3b20cf178954366701fe5
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/a9/a61830fbf4e84999d3b20cf178954366701fe5
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/a9/a61830fbf4e84999d3b20cf178954366701fe5
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/c7/85b65bf16928b58567cb23669125c0ccd25a4f b/tests/gitea-repositories-meta/user2/utf8.git/objects/c7/85b65bf16928b58567cb23669125c0ccd25a4f
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/c7/85b65bf16928b58567cb23669125c0ccd25a4f
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/c7/85b65bf16928b58567cb23669125c0ccd25a4f
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/e9/63733b8a355cf860c465b4af7b236a6ef08783 b/tests/gitea-repositories-meta/user2/utf8.git/objects/e9/63733b8a355cf860c465b4af7b236a6ef08783
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/e9/63733b8a355cf860c465b4af7b236a6ef08783
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/e9/63733b8a355cf860c465b4af7b236a6ef08783
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/eb/f146f803fccbc1471ef01d8fa0fe12c14e61a5 b/tests/gitea-repositories-meta/user2/utf8.git/objects/eb/f146f803fccbc1471ef01d8fa0fe12c14e61a5
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/eb/f146f803fccbc1471ef01d8fa0fe12c14e61a5
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/eb/f146f803fccbc1471ef01d8fa0fe12c14e61a5
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/ee/9686cb562f492f64381bff7f298b2a1c67a141 b/tests/gitea-repositories-meta/user2/utf8.git/objects/ee/9686cb562f492f64381bff7f298b2a1c67a141
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/ee/9686cb562f492f64381bff7f298b2a1c67a141
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/ee/9686cb562f492f64381bff7f298b2a1c67a141
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/f4/02ff67c0b3161c3988dbf6188e6e0df257fd75 b/tests/gitea-repositories-meta/user2/utf8.git/objects/f4/02ff67c0b3161c3988dbf6188e6e0df257fd75
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/f4/02ff67c0b3161c3988dbf6188e6e0df257fd75
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/f4/02ff67c0b3161c3988dbf6188e6e0df257fd75
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/objects/info/packs b/tests/gitea-repositories-meta/user2/utf8.git/objects/info/packs
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/objects/info/packs
rename to tests/gitea-repositories-meta/user2/utf8.git/objects/info/packs
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/Grüßen b/tests/gitea-repositories-meta/user2/utf8.git/refs/heads/Grüßen
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/Grüßen
rename to tests/gitea-repositories-meta/user2/utf8.git/refs/heads/Grüßen
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/Plus+Is+Not+Space b/tests/gitea-repositories-meta/user2/utf8.git/refs/heads/Plus+Is+Not+Space
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/Plus+Is+Not+Space
rename to tests/gitea-repositories-meta/user2/utf8.git/refs/heads/Plus+Is+Not+Space
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/master b/tests/gitea-repositories-meta/user2/utf8.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/master
rename to tests/gitea-repositories-meta/user2/utf8.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/ГлавнаяВетка b/tests/gitea-repositories-meta/user2/utf8.git/refs/heads/ГлавнаяВетка
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/ГлавнаяВетка
rename to tests/gitea-repositories-meta/user2/utf8.git/refs/heads/ГлавнаяВетка
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/а/б/в b/tests/gitea-repositories-meta/user2/utf8.git/refs/heads/а/б/в
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/а/б/в
rename to tests/gitea-repositories-meta/user2/utf8.git/refs/heads/а/б/в
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/ブランチ b/tests/gitea-repositories-meta/user2/utf8.git/refs/heads/ブランチ
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/refs/heads/ブランチ
rename to tests/gitea-repositories-meta/user2/utf8.git/refs/heads/ブランチ
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/refs/tags/Ё/人 b/tests/gitea-repositories-meta/user2/utf8.git/refs/tags/Ё/人
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/refs/tags/Ё/人
rename to tests/gitea-repositories-meta/user2/utf8.git/refs/tags/Ё/人
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/refs/tags/Тэг b/tests/gitea-repositories-meta/user2/utf8.git/refs/tags/Тэг
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/refs/tags/Тэг
rename to tests/gitea-repositories-meta/user2/utf8.git/refs/tags/Тэг
diff --git a/integrations/gitea-repositories-meta/user2/utf8.git/refs/tags/タグ b/tests/gitea-repositories-meta/user2/utf8.git/refs/tags/タグ
similarity index 100%
rename from integrations/gitea-repositories-meta/user2/utf8.git/refs/tags/タグ
rename to tests/gitea-repositories-meta/user2/utf8.git/refs/tags/タグ
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/HEAD b/tests/gitea-repositories-meta/user27/repo49.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/HEAD
rename to tests/gitea-repositories-meta/user27/repo49.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/config b/tests/gitea-repositories-meta/user27/repo49.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/config
rename to tests/gitea-repositories-meta/user27/repo49.git/config
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/description b/tests/gitea-repositories-meta/user27/repo49.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/description
rename to tests/gitea-repositories-meta/user27/repo49.git/description
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/hooks/post-receive b/tests/gitea-repositories-meta/user27/repo49.git/hooks/post-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/hooks/post-receive
rename to tests/gitea-repositories-meta/user27/repo49.git/hooks/post-receive
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/hooks/post-receive.d/gitea b/tests/gitea-repositories-meta/user27/repo49.git/hooks/post-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/hooks/post-receive.d/gitea
rename to tests/gitea-repositories-meta/user27/repo49.git/hooks/post-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/hooks/pre-receive b/tests/gitea-repositories-meta/user27/repo49.git/hooks/pre-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/hooks/pre-receive
rename to tests/gitea-repositories-meta/user27/repo49.git/hooks/pre-receive
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/hooks/pre-receive.d/gitea b/tests/gitea-repositories-meta/user27/repo49.git/hooks/pre-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/hooks/pre-receive.d/gitea
rename to tests/gitea-repositories-meta/user27/repo49.git/hooks/pre-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/hooks/update b/tests/gitea-repositories-meta/user27/repo49.git/hooks/update
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/hooks/update
rename to tests/gitea-repositories-meta/user27/repo49.git/hooks/update
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/hooks/update.d/gitea b/tests/gitea-repositories-meta/user27/repo49.git/hooks/update.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/hooks/update.d/gitea
rename to tests/gitea-repositories-meta/user27/repo49.git/hooks/update.d/gitea
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/info/exclude b/tests/gitea-repositories-meta/user27/repo49.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/info/exclude
rename to tests/gitea-repositories-meta/user27/repo49.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/info/refs b/tests/gitea-repositories-meta/user27/repo49.git/info/refs
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/info/refs
rename to tests/gitea-repositories-meta/user27/repo49.git/info/refs
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/objects/47/34b1f84a367fa1b81c31aa4234a5bad11cafa3 b/tests/gitea-repositories-meta/user27/repo49.git/objects/47/34b1f84a367fa1b81c31aa4234a5bad11cafa3
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/objects/47/34b1f84a367fa1b81c31aa4234a5bad11cafa3
rename to tests/gitea-repositories-meta/user27/repo49.git/objects/47/34b1f84a367fa1b81c31aa4234a5bad11cafa3
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/objects/4d/31f3a12656368a8d9180f431d40d0fc408be2d b/tests/gitea-repositories-meta/user27/repo49.git/objects/4d/31f3a12656368a8d9180f431d40d0fc408be2d
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/objects/4d/31f3a12656368a8d9180f431d40d0fc408be2d
rename to tests/gitea-repositories-meta/user27/repo49.git/objects/4d/31f3a12656368a8d9180f431d40d0fc408be2d
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/objects/51/f84af231345367fd5d61ceb89efb3b6d757061 b/tests/gitea-repositories-meta/user27/repo49.git/objects/51/f84af231345367fd5d61ceb89efb3b6d757061
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/objects/51/f84af231345367fd5d61ceb89efb3b6d757061
rename to tests/gitea-repositories-meta/user27/repo49.git/objects/51/f84af231345367fd5d61ceb89efb3b6d757061
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/objects/79/3aa682b06ae032641abf70c5dfeade28c07c52 b/tests/gitea-repositories-meta/user27/repo49.git/objects/79/3aa682b06ae032641abf70c5dfeade28c07c52
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/objects/79/3aa682b06ae032641abf70c5dfeade28c07c52
rename to tests/gitea-repositories-meta/user27/repo49.git/objects/79/3aa682b06ae032641abf70c5dfeade28c07c52
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/objects/aa/cbdfe9e1c4b47f60abe81849045fa4e96f1d75 b/tests/gitea-repositories-meta/user27/repo49.git/objects/aa/cbdfe9e1c4b47f60abe81849045fa4e96f1d75
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/objects/aa/cbdfe9e1c4b47f60abe81849045fa4e96f1d75
rename to tests/gitea-repositories-meta/user27/repo49.git/objects/aa/cbdfe9e1c4b47f60abe81849045fa4e96f1d75
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/objects/dd/392e939ea4936b2459219c9c9a1f25547ccaeb b/tests/gitea-repositories-meta/user27/repo49.git/objects/dd/392e939ea4936b2459219c9c9a1f25547ccaeb
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/objects/dd/392e939ea4936b2459219c9c9a1f25547ccaeb
rename to tests/gitea-repositories-meta/user27/repo49.git/objects/dd/392e939ea4936b2459219c9c9a1f25547ccaeb
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/objects/f2/8eeca3df7614fd4f10c1030f13feb418ef3c6f b/tests/gitea-repositories-meta/user27/repo49.git/objects/f2/8eeca3df7614fd4f10c1030f13feb418ef3c6f
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/objects/f2/8eeca3df7614fd4f10c1030f13feb418ef3c6f
rename to tests/gitea-repositories-meta/user27/repo49.git/objects/f2/8eeca3df7614fd4f10c1030f13feb418ef3c6f
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/objects/info/packs b/tests/gitea-repositories-meta/user27/repo49.git/objects/info/packs
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/objects/info/packs
rename to tests/gitea-repositories-meta/user27/repo49.git/objects/info/packs
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/refs/heads/master b/tests/gitea-repositories-meta/user27/repo49.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/refs/heads/master
rename to tests/gitea-repositories-meta/user27/repo49.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user27/repo49.git/refs/heads/test/archive b/tests/gitea-repositories-meta/user27/repo49.git/refs/heads/test/archive
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/repo49.git/refs/heads/test/archive
rename to tests/gitea-repositories-meta/user27/repo49.git/refs/heads/test/archive
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/HEAD b/tests/gitea-repositories-meta/user27/template1.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/HEAD
rename to tests/gitea-repositories-meta/user27/template1.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/config b/tests/gitea-repositories-meta/user27/template1.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/config
rename to tests/gitea-repositories-meta/user27/template1.git/config
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/description b/tests/gitea-repositories-meta/user27/template1.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/description
rename to tests/gitea-repositories-meta/user27/template1.git/description
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/hooks/post-receive b/tests/gitea-repositories-meta/user27/template1.git/hooks/post-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/hooks/post-receive
rename to tests/gitea-repositories-meta/user27/template1.git/hooks/post-receive
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/hooks/post-receive.d/gitea b/tests/gitea-repositories-meta/user27/template1.git/hooks/post-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/hooks/post-receive.d/gitea
rename to tests/gitea-repositories-meta/user27/template1.git/hooks/post-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/hooks/pre-receive b/tests/gitea-repositories-meta/user27/template1.git/hooks/pre-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/hooks/pre-receive
rename to tests/gitea-repositories-meta/user27/template1.git/hooks/pre-receive
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/hooks/pre-receive.d/gitea b/tests/gitea-repositories-meta/user27/template1.git/hooks/pre-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/hooks/pre-receive.d/gitea
rename to tests/gitea-repositories-meta/user27/template1.git/hooks/pre-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/hooks/update b/tests/gitea-repositories-meta/user27/template1.git/hooks/update
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/hooks/update
rename to tests/gitea-repositories-meta/user27/template1.git/hooks/update
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/hooks/update.d/gitea b/tests/gitea-repositories-meta/user27/template1.git/hooks/update.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/hooks/update.d/gitea
rename to tests/gitea-repositories-meta/user27/template1.git/hooks/update.d/gitea
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/info/exclude b/tests/gitea-repositories-meta/user27/template1.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/info/exclude
rename to tests/gitea-repositories-meta/user27/template1.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/info/refs b/tests/gitea-repositories-meta/user27/template1.git/info/refs
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/info/refs
rename to tests/gitea-repositories-meta/user27/template1.git/info/refs
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/objects/47/34b1f84a367fa1b81c31aa4234a5bad11cafa3 b/tests/gitea-repositories-meta/user27/template1.git/objects/47/34b1f84a367fa1b81c31aa4234a5bad11cafa3
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/objects/47/34b1f84a367fa1b81c31aa4234a5bad11cafa3
rename to tests/gitea-repositories-meta/user27/template1.git/objects/47/34b1f84a367fa1b81c31aa4234a5bad11cafa3
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/objects/4d/31f3a12656368a8d9180f431d40d0fc408be2d b/tests/gitea-repositories-meta/user27/template1.git/objects/4d/31f3a12656368a8d9180f431d40d0fc408be2d
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/objects/4d/31f3a12656368a8d9180f431d40d0fc408be2d
rename to tests/gitea-repositories-meta/user27/template1.git/objects/4d/31f3a12656368a8d9180f431d40d0fc408be2d
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/objects/51/f84af231345367fd5d61ceb89efb3b6d757061 b/tests/gitea-repositories-meta/user27/template1.git/objects/51/f84af231345367fd5d61ceb89efb3b6d757061
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/objects/51/f84af231345367fd5d61ceb89efb3b6d757061
rename to tests/gitea-repositories-meta/user27/template1.git/objects/51/f84af231345367fd5d61ceb89efb3b6d757061
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/objects/79/3aa682b06ae032641abf70c5dfeade28c07c52 b/tests/gitea-repositories-meta/user27/template1.git/objects/79/3aa682b06ae032641abf70c5dfeade28c07c52
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/objects/79/3aa682b06ae032641abf70c5dfeade28c07c52
rename to tests/gitea-repositories-meta/user27/template1.git/objects/79/3aa682b06ae032641abf70c5dfeade28c07c52
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/objects/aa/cbdfe9e1c4b47f60abe81849045fa4e96f1d75 b/tests/gitea-repositories-meta/user27/template1.git/objects/aa/cbdfe9e1c4b47f60abe81849045fa4e96f1d75
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/objects/aa/cbdfe9e1c4b47f60abe81849045fa4e96f1d75
rename to tests/gitea-repositories-meta/user27/template1.git/objects/aa/cbdfe9e1c4b47f60abe81849045fa4e96f1d75
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/objects/dd/392e939ea4936b2459219c9c9a1f25547ccaeb b/tests/gitea-repositories-meta/user27/template1.git/objects/dd/392e939ea4936b2459219c9c9a1f25547ccaeb
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/objects/dd/392e939ea4936b2459219c9c9a1f25547ccaeb
rename to tests/gitea-repositories-meta/user27/template1.git/objects/dd/392e939ea4936b2459219c9c9a1f25547ccaeb
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/objects/f2/8eeca3df7614fd4f10c1030f13feb418ef3c6f b/tests/gitea-repositories-meta/user27/template1.git/objects/f2/8eeca3df7614fd4f10c1030f13feb418ef3c6f
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/objects/f2/8eeca3df7614fd4f10c1030f13feb418ef3c6f
rename to tests/gitea-repositories-meta/user27/template1.git/objects/f2/8eeca3df7614fd4f10c1030f13feb418ef3c6f
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/objects/info/packs b/tests/gitea-repositories-meta/user27/template1.git/objects/info/packs
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/objects/info/packs
rename to tests/gitea-repositories-meta/user27/template1.git/objects/info/packs
diff --git a/integrations/gitea-repositories-meta/user27/template1.git/refs/heads/master b/tests/gitea-repositories-meta/user27/template1.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user27/template1.git/refs/heads/master
rename to tests/gitea-repositories-meta/user27/template1.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/HEAD b/tests/gitea-repositories-meta/user3/repo3.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/HEAD
rename to tests/gitea-repositories-meta/user3/repo3.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/config b/tests/gitea-repositories-meta/user3/repo3.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/config
rename to tests/gitea-repositories-meta/user3/repo3.git/config
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/description b/tests/gitea-repositories-meta/user3/repo3.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/description
rename to tests/gitea-repositories-meta/user3/repo3.git/description
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/post-receive b/tests/gitea-repositories-meta/user3/repo3.git/hooks/post-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/hooks/post-receive
rename to tests/gitea-repositories-meta/user3/repo3.git/hooks/post-receive
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/post-receive.d/gitea b/tests/gitea-repositories-meta/user3/repo3.git/hooks/post-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/hooks/post-receive.d/gitea
rename to tests/gitea-repositories-meta/user3/repo3.git/hooks/post-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive b/tests/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive
rename to tests/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive.d/gitea b/tests/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive.d/gitea
rename to tests/gitea-repositories-meta/user3/repo3.git/hooks/pre-receive.d/gitea
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/update b/tests/gitea-repositories-meta/user3/repo3.git/hooks/update
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/hooks/update
rename to tests/gitea-repositories-meta/user3/repo3.git/hooks/update
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/hooks/update.d/gitea b/tests/gitea-repositories-meta/user3/repo3.git/hooks/update.d/gitea
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/hooks/update.d/gitea
rename to tests/gitea-repositories-meta/user3/repo3.git/hooks/update.d/gitea
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/info/exclude b/tests/gitea-repositories-meta/user3/repo3.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/info/exclude
rename to tests/gitea-repositories-meta/user3/repo3.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/objects/20/ade30d25e0ecaeec84e7f542a8456900858240 b/tests/gitea-repositories-meta/user3/repo3.git/objects/20/ade30d25e0ecaeec84e7f542a8456900858240
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/objects/20/ade30d25e0ecaeec84e7f542a8456900858240
rename to tests/gitea-repositories-meta/user3/repo3.git/objects/20/ade30d25e0ecaeec84e7f542a8456900858240
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/objects/27/74debeea6dc742cc4971a92db0e08b95b60588 b/tests/gitea-repositories-meta/user3/repo3.git/objects/27/74debeea6dc742cc4971a92db0e08b95b60588
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/objects/27/74debeea6dc742cc4971a92db0e08b95b60588
rename to tests/gitea-repositories-meta/user3/repo3.git/objects/27/74debeea6dc742cc4971a92db0e08b95b60588
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/objects/2a/47ca4b614a9f5a43abbd5ad851a54a616ffee6 b/tests/gitea-repositories-meta/user3/repo3.git/objects/2a/47ca4b614a9f5a43abbd5ad851a54a616ffee6
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/objects/2a/47ca4b614a9f5a43abbd5ad851a54a616ffee6
rename to tests/gitea-repositories-meta/user3/repo3.git/objects/2a/47ca4b614a9f5a43abbd5ad851a54a616ffee6
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/objects/2f/9b22fd3159a43b7b4e5dd806fcd544edf8716f b/tests/gitea-repositories-meta/user3/repo3.git/objects/2f/9b22fd3159a43b7b4e5dd806fcd544edf8716f
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/objects/2f/9b22fd3159a43b7b4e5dd806fcd544edf8716f
rename to tests/gitea-repositories-meta/user3/repo3.git/objects/2f/9b22fd3159a43b7b4e5dd806fcd544edf8716f
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/objects/d2/2b4d4daa5be07329fcef6ed458f00cf3392da0 b/tests/gitea-repositories-meta/user3/repo3.git/objects/d2/2b4d4daa5be07329fcef6ed458f00cf3392da0
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/objects/d2/2b4d4daa5be07329fcef6ed458f00cf3392da0
rename to tests/gitea-repositories-meta/user3/repo3.git/objects/d2/2b4d4daa5be07329fcef6ed458f00cf3392da0
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/objects/d5/6a3073c1dbb7b15963110a049d50cdb5db99fc b/tests/gitea-repositories-meta/user3/repo3.git/objects/d5/6a3073c1dbb7b15963110a049d50cdb5db99fc
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/objects/d5/6a3073c1dbb7b15963110a049d50cdb5db99fc
rename to tests/gitea-repositories-meta/user3/repo3.git/objects/d5/6a3073c1dbb7b15963110a049d50cdb5db99fc
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/objects/ec/f0db3c1ec806522de4b491fb9a3c7457398c61 b/tests/gitea-repositories-meta/user3/repo3.git/objects/ec/f0db3c1ec806522de4b491fb9a3c7457398c61
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/objects/ec/f0db3c1ec806522de4b491fb9a3c7457398c61
rename to tests/gitea-repositories-meta/user3/repo3.git/objects/ec/f0db3c1ec806522de4b491fb9a3c7457398c61
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/objects/ee/16d127df463aa491e08958120f2108b02468df b/tests/gitea-repositories-meta/user3/repo3.git/objects/ee/16d127df463aa491e08958120f2108b02468df
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/objects/ee/16d127df463aa491e08958120f2108b02468df
rename to tests/gitea-repositories-meta/user3/repo3.git/objects/ee/16d127df463aa491e08958120f2108b02468df
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/refs/heads/master b/tests/gitea-repositories-meta/user3/repo3.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/refs/heads/master
rename to tests/gitea-repositories-meta/user3/repo3.git/refs/heads/master
diff --git a/integrations/gitea-repositories-meta/user3/repo3.git/refs/heads/test_branch b/tests/gitea-repositories-meta/user3/repo3.git/refs/heads/test_branch
similarity index 100%
rename from integrations/gitea-repositories-meta/user3/repo3.git/refs/heads/test_branch
rename to tests/gitea-repositories-meta/user3/repo3.git/refs/heads/test_branch
diff --git a/integrations/gitea-repositories-meta/user30/empty.git/HEAD b/tests/gitea-repositories-meta/user30/empty.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user30/empty.git/HEAD
rename to tests/gitea-repositories-meta/user30/empty.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user30/empty.git/config b/tests/gitea-repositories-meta/user30/empty.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user30/empty.git/config
rename to tests/gitea-repositories-meta/user30/empty.git/config
diff --git a/integrations/gitea-repositories-meta/user5/repo4.git/HEAD b/tests/gitea-repositories-meta/user5/repo4.git/HEAD
similarity index 100%
rename from integrations/gitea-repositories-meta/user5/repo4.git/HEAD
rename to tests/gitea-repositories-meta/user5/repo4.git/HEAD
diff --git a/integrations/gitea-repositories-meta/user5/repo4.git/config b/tests/gitea-repositories-meta/user5/repo4.git/config
similarity index 100%
rename from integrations/gitea-repositories-meta/user5/repo4.git/config
rename to tests/gitea-repositories-meta/user5/repo4.git/config
diff --git a/integrations/gitea-repositories-meta/user5/repo4.git/description b/tests/gitea-repositories-meta/user5/repo4.git/description
similarity index 100%
rename from integrations/gitea-repositories-meta/user5/repo4.git/description
rename to tests/gitea-repositories-meta/user5/repo4.git/description
diff --git a/integrations/gitea-repositories-meta/user5/repo4.git/info/exclude b/tests/gitea-repositories-meta/user5/repo4.git/info/exclude
similarity index 100%
rename from integrations/gitea-repositories-meta/user5/repo4.git/info/exclude
rename to tests/gitea-repositories-meta/user5/repo4.git/info/exclude
diff --git a/integrations/gitea-repositories-meta/user5/repo4.git/objects/16/dfebd1ed3905d78d7e061e945fc9c34afe4e81 b/tests/gitea-repositories-meta/user5/repo4.git/objects/16/dfebd1ed3905d78d7e061e945fc9c34afe4e81
similarity index 100%
rename from integrations/gitea-repositories-meta/user5/repo4.git/objects/16/dfebd1ed3905d78d7e061e945fc9c34afe4e81
rename to tests/gitea-repositories-meta/user5/repo4.git/objects/16/dfebd1ed3905d78d7e061e945fc9c34afe4e81
diff --git a/integrations/gitea-repositories-meta/user5/repo4.git/objects/c1/202ad022ae7d3a6d2474dc76d5a0c8e87cdc0f b/tests/gitea-repositories-meta/user5/repo4.git/objects/c1/202ad022ae7d3a6d2474dc76d5a0c8e87cdc0f
similarity index 100%
rename from integrations/gitea-repositories-meta/user5/repo4.git/objects/c1/202ad022ae7d3a6d2474dc76d5a0c8e87cdc0f
rename to tests/gitea-repositories-meta/user5/repo4.git/objects/c1/202ad022ae7d3a6d2474dc76d5a0c8e87cdc0f
diff --git a/integrations/gitea-repositories-meta/user5/repo4.git/objects/c7/cd3cd144e6d23c9d6f3d07e52b2c1a956e0338 b/tests/gitea-repositories-meta/user5/repo4.git/objects/c7/cd3cd144e6d23c9d6f3d07e52b2c1a956e0338
similarity index 100%
rename from integrations/gitea-repositories-meta/user5/repo4.git/objects/c7/cd3cd144e6d23c9d6f3d07e52b2c1a956e0338
rename to tests/gitea-repositories-meta/user5/repo4.git/objects/c7/cd3cd144e6d23c9d6f3d07e52b2c1a956e0338
diff --git a/integrations/gitea-repositories-meta/user5/repo4.git/refs/heads/master b/tests/gitea-repositories-meta/user5/repo4.git/refs/heads/master
similarity index 100%
rename from integrations/gitea-repositories-meta/user5/repo4.git/refs/heads/master
rename to tests/gitea-repositories-meta/user5/repo4.git/refs/heads/master
diff --git a/integrations/README.md b/tests/integration/README.md
similarity index 93%
rename from integrations/README.md
rename to tests/integration/README.md
index 40cdcde474..636949df38 100644
--- a/integrations/README.md
+++ b/tests/integration/README.md
@@ -1,11 +1,13 @@
-# Integrations tests
+# Integration tests
 
 Integration tests can be run with make commands for the
 appropriate backends, namely:
 ```shell
-make test-mysql
-make test-pgsql
 make test-sqlite
+make test-pgsql
+make test-mysql
+make test-mysql8
+make test-mssql
 ```
 
 Make sure to perform a clean build before running tests:
@@ -18,13 +20,13 @@ make clean build
 drone exec --local --build-event "pull_request"
 ```
 
-## Run sqlite integrations tests
+## Run sqlite integration tests
 Start tests
 ```
 make test-sqlite
 ```
 
-## Run MySQL integrations tests
+## Run MySQL integration tests
 Setup a MySQL database inside docker
 ```
 docker run -e "MYSQL_DATABASE=test" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" -p 3306:3306 --rm --name mysql mysql:latest #(just ctrl-c to stop db and clean the container)
@@ -35,7 +37,7 @@ Start tests based on the database container
 TEST_MYSQL_HOST=localhost:3306 TEST_MYSQL_DBNAME=test TEST_MYSQL_USERNAME=root TEST_MYSQL_PASSWORD='' make test-mysql
 ```
 
-## Run pgsql integrations tests
+## Run pgsql integration tests
 Setup a pgsql database inside docker
 ```
 docker run -e "POSTGRES_DB=test" -p 5432:5432 --rm --name pgsql postgres:latest #(just ctrl-c to stop db and clean the container)
@@ -45,7 +47,7 @@ Start tests based on the database container
 TEST_PGSQL_HOST=localhost:5432 TEST_PGSQL_DBNAME=test TEST_PGSQL_USERNAME=postgres TEST_PGSQL_PASSWORD=postgres make test-pgsql
 ```
 
-## Run mssql integrations tests
+## Run mssql integration tests
 Setup a mssql database inside docker
 ```
 docker run -e "ACCEPT_EULA=Y" -e "MSSQL_PID=Standard" -e "SA_PASSWORD=MwantsaSecurePassword1" -p 1433:1433 --rm --name mssql microsoft/mssql-server-linux:latest #(just ctrl-c to stop db and clean the container)
diff --git a/integrations/README_ZH.md b/tests/integration/README_ZH.md
similarity index 98%
rename from integrations/README_ZH.md
rename to tests/integration/README_ZH.md
index eebb14de73..3840232472 100644
--- a/integrations/README_ZH.md
+++ b/tests/integration/README_ZH.md
@@ -43,7 +43,7 @@ docker run -e "POSTGRES_DB=test" -p 5432:5432 --rm --name pgsql postgres:14 #(ju
 TEST_PGSQL_HOST=localhost:5432 TEST_PGSQL_DBNAME=test TEST_PGSQL_USERNAME=postgres TEST_PGSQL_PASSWORD=postgres make test-pgsql
 ```
 
-## Run mssql integrations tests
+## Run mssql integration tests
 同上,首先在 docker 容器里部署一个 mssql 数据库
 ```
 docker run -e "ACCEPT_EULA=Y" -e "MSSQL_PID=Standard" -e "SA_PASSWORD=MwantsaSecurePassword1" -p 1433:1433 --rm --name mssql microsoft/mssql-server-linux:latest #(just ctrl-c to stop db and clean the container) 
diff --git a/integrations/admin_user_test.go b/tests/integration/admin_user_test.go
similarity index 92%
rename from integrations/admin_user_test.go
rename to tests/integration/admin_user_test.go
index 2225c903df..ffe3f670fe 100644
--- a/integrations/admin_user_test.go
+++ b/tests/integration/admin_user_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -11,12 +11,13 @@ import (
 
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAdminViewUsers(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user1")
 	req := NewRequest(t, "GET", "/admin/users")
@@ -28,7 +29,7 @@ func TestAdminViewUsers(t *testing.T) {
 }
 
 func TestAdminViewUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user1")
 	req := NewRequest(t, "GET", "/admin/users/1")
@@ -40,7 +41,7 @@ func TestAdminViewUser(t *testing.T) {
 }
 
 func TestAdminEditUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	testSuccessfullEdit(t, user_model.User{ID: 2, Name: "newusername", LoginName: "otherlogin", Email: "new@e-mail.gitea"})
 }
@@ -68,7 +69,7 @@ func makeRequest(t *testing.T, formData user_model.User, headerCode int) {
 }
 
 func TestAdminDeleteUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user1")
 
diff --git a/integrations/api_activitypub_person_test.go b/tests/integration/api_activitypub_person_test.go
similarity index 99%
rename from integrations/api_activitypub_person_test.go
rename to tests/integration/api_activitypub_person_test.go
index c0548df0bc..e7ef79d156 100644
--- a/integrations/api_activitypub_person_test.go
+++ b/tests/integration/api_activitypub_person_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"context"
diff --git a/integrations/api_admin_org_test.go b/tests/integration/api_admin_org_test.go
similarity index 97%
rename from integrations/api_admin_org_test.go
rename to tests/integration/api_admin_org_test.go
index 8f36850a1a..720f6fc6b6 100644
--- a/integrations/api_admin_org_test.go
+++ b/tests/integration/api_admin_org_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -13,6 +13,7 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -70,7 +71,7 @@ func TestAPIAdminOrgCreateBadVisibility(t *testing.T) {
 }
 
 func TestAPIAdminOrgCreateNotAdmin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	nonAdminUsername := "user2"
 	session := loginUser(t, nonAdminUsername)
 	token := getTokenForLoggedInUser(t, session)
diff --git a/integrations/api_admin_test.go b/tests/integration/api_admin_test.go
similarity index 95%
rename from integrations/api_admin_test.go
rename to tests/integration/api_admin_test.go
index e32b866844..dea0bdd063 100644
--- a/integrations/api_admin_test.go
+++ b/tests/integration/api_admin_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -14,12 +14,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/json"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	// user1 is an admin user
 	session := loginUser(t, "user1")
 	keyOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user2"})
@@ -48,7 +49,7 @@ func TestAPIAdminCreateAndDeleteSSHKey(t *testing.T) {
 }
 
 func TestAPIAdminDeleteMissingSSHKey(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	// user1 is an admin user
 	session := loginUser(t, "user1")
 
@@ -58,7 +59,7 @@ func TestAPIAdminDeleteMissingSSHKey(t *testing.T) {
 }
 
 func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	adminUsername := "user1"
 	normalUsername := "user2"
 	session := loginUser(t, adminUsername)
@@ -81,7 +82,7 @@ func TestAPIAdminDeleteUnauthorizedKey(t *testing.T) {
 }
 
 func TestAPISudoUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	adminUsername := "user1"
 	normalUsername := "user2"
 	session := loginUser(t, adminUsername)
@@ -97,7 +98,7 @@ func TestAPISudoUser(t *testing.T) {
 }
 
 func TestAPISudoUserForbidden(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	adminUsername := "user1"
 	normalUsername := "user2"
 
@@ -110,7 +111,7 @@ func TestAPISudoUserForbidden(t *testing.T) {
 }
 
 func TestAPIListUsers(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	adminUsername := "user1"
 	session := loginUser(t, adminUsername)
 	token := getTokenForLoggedInUser(t, session)
@@ -133,13 +134,13 @@ func TestAPIListUsers(t *testing.T) {
 }
 
 func TestAPIListUsersNotLoggedIn(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequest(t, "GET", "/api/v1/admin/users")
 	MakeRequest(t, req, http.StatusUnauthorized)
 }
 
 func TestAPIListUsersNonAdmin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	nonAdminUsername := "user2"
 	session := loginUser(t, nonAdminUsername)
 	token := getTokenForLoggedInUser(t, session)
@@ -148,7 +149,7 @@ func TestAPIListUsersNonAdmin(t *testing.T) {
 }
 
 func TestAPICreateUserInvalidEmail(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	adminUsername := "user1"
 	session := loginUser(t, adminUsername)
 	token := getTokenForLoggedInUser(t, session)
@@ -167,7 +168,7 @@ func TestAPICreateUserInvalidEmail(t *testing.T) {
 }
 
 func TestAPIEditUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	adminUsername := "user1"
 	session := loginUser(t, adminUsername)
 	token := getTokenForLoggedInUser(t, session)
diff --git a/integrations/api_branch_test.go b/tests/integration/api_branch_test.go
similarity index 96%
rename from integrations/api_branch_test.go
rename to tests/integration/api_branch_test.go
index e137331343..bdfdd3c752 100644
--- a/integrations/api_branch_test.go
+++ b/tests/integration/api_branch_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -10,6 +10,7 @@ import (
 	"testing"
 
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -87,7 +88,7 @@ func testAPIDeleteBranch(t *testing.T, branchName string, expectedHTTPStatus int
 }
 
 func TestAPIGetBranch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	for _, test := range []struct {
 		BranchName string
 		Exists     bool
@@ -111,7 +112,7 @@ func testAPICreateBranches(t *testing.T, giteaURL *url.URL) {
 	giteaURL.Path = ctx.GitPath()
 
 	t.Run("CreateRepo", doAPICreateRepository(ctx, false))
-	tests := []struct {
+	testCases := []struct {
 		OldBranch          string
 		NewBranch          string
 		ExpectedHTTPStatus int
@@ -147,8 +148,8 @@ func testAPICreateBranches(t *testing.T, giteaURL *url.URL) {
 			ExpectedHTTPStatus: http.StatusNotFound,
 		},
 	}
-	for _, test := range tests {
-		defer resetFixtures(t)
+	for _, test := range testCases {
+		defer tests.ResetFixtures(t)
 		session := ctx.Session
 		testAPICreateBranch(t, session, "user2", "my-noo-repo", test.OldBranch, test.NewBranch, test.ExpectedHTTPStatus)
 	}
@@ -173,7 +174,7 @@ func testAPICreateBranch(t testing.TB, session *TestSession, user, repo, oldBran
 }
 
 func TestAPIBranchProtection(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// Branch protection only on branch that exist
 	testAPICreateBranchProtection(t, "master/doesnotexist", http.StatusNotFound)
diff --git a/integrations/api_comment_test.go b/tests/integration/api_comment_test.go
similarity index 96%
rename from integrations/api_comment_test.go
rename to tests/integration/api_comment_test.go
index ac1079b02d..126d886842 100644
--- a/integrations/api_comment_test.go
+++ b/tests/integration/api_comment_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -16,12 +16,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/convert"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIListRepoComments(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{},
 		unittest.Cond("type = ?", issues_model.CommentTypeComment))
@@ -67,7 +68,7 @@ func TestAPIListRepoComments(t *testing.T) {
 }
 
 func TestAPIListIssueComments(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{},
 		unittest.Cond("type = ?", issues_model.CommentTypeComment))
@@ -88,7 +89,7 @@ func TestAPIListIssueComments(t *testing.T) {
 }
 
 func TestAPICreateComment(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	const commentBody = "Comment body"
 
 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{})
@@ -111,7 +112,7 @@ func TestAPICreateComment(t *testing.T) {
 }
 
 func TestAPIGetComment(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 2})
 	assert.NoError(t, comment.LoadIssue())
@@ -138,7 +139,7 @@ func TestAPIGetComment(t *testing.T) {
 }
 
 func TestAPIEditComment(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	const newCommentBody = "This is the new comment body"
 
 	comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{},
@@ -164,7 +165,7 @@ func TestAPIEditComment(t *testing.T) {
 }
 
 func TestAPIDeleteComment(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{},
 		unittest.Cond("type = ?", issues_model.CommentTypeComment))
@@ -182,7 +183,7 @@ func TestAPIDeleteComment(t *testing.T) {
 }
 
 func TestAPIListIssueTimeline(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// load comment
 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
diff --git a/integrations/api_fork_test.go b/tests/integration/api_fork_test.go
similarity index 84%
rename from integrations/api_fork_test.go
rename to tests/integration/api_fork_test.go
index 4f3b023312..131dcf70bb 100644
--- a/integrations/api_fork_test.go
+++ b/tests/integration/api_fork_test.go
@@ -2,17 +2,18 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
 	"testing"
 
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 )
 
 func TestCreateForkNoLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/forks", &api.CreateForkOption{})
 	MakeRequest(t, req, http.StatusUnauthorized)
 }
diff --git a/integrations/api_gpg_keys_test.go b/tests/integration/api_gpg_keys_test.go
similarity index 99%
rename from integrations/api_gpg_keys_test.go
rename to tests/integration/api_gpg_keys_test.go
index 38341aecff..0ad876c9b9 100644
--- a/integrations/api_gpg_keys_test.go
+++ b/tests/integration/api_gpg_keys_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -11,6 +11,7 @@ import (
 	"testing"
 
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -18,7 +19,7 @@ import (
 type makeRequestFunc func(testing.TB, *http.Request, int) *httptest.ResponseRecorder
 
 func TestGPGKeys(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user2")
 	token := getTokenForLoggedInUser(t, session)
 
diff --git a/integrations/api_helper_for_declarative_test.go b/tests/integration/api_helper_for_declarative_test.go
similarity index 99%
rename from integrations/api_helper_for_declarative_test.go
rename to tests/integration/api_helper_for_declarative_test.go
index 181a646946..5a798f79f0 100644
--- a/integrations/api_helper_for_declarative_test.go
+++ b/tests/integration/api_helper_for_declarative_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"context"
diff --git a/integrations/api_httpsig_test.go b/tests/integration/api_httpsig_test.go
similarity index 98%
rename from integrations/api_httpsig_test.go
rename to tests/integration/api_httpsig_test.go
index 7197e9afb9..80b3c586b4 100644
--- a/integrations/api_httpsig_test.go
+++ b/tests/integration/api_httpsig_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"encoding/base64"
@@ -12,6 +12,7 @@ import (
 	"testing"
 
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/go-fed/httpsig"
 	"golang.org/x/crypto/ssh"
@@ -50,7 +51,7 @@ fhTNAzWwZoQ91aHdAAAAFHUwMDIyMTQ2QGljdHMtcC1ueC03AQIDBAUG
 
 func TestHTTPSigPubKey(t *testing.T) {
 	// Add our public key to user1
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user1")
 	token := url.QueryEscape(getTokenForLoggedInUser(t, session))
 	keysURL := fmt.Sprintf("/api/v1/user/keys?token=%s", token)
@@ -87,7 +88,7 @@ func TestHTTPSigPubKey(t *testing.T) {
 
 func TestHTTPSigCert(t *testing.T) {
 	// Add our public key to user1
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user1")
 
 	csrf := GetCSRF(t, session, "/user/settings/keys")
diff --git a/integrations/api_issue_label_test.go b/tests/integration/api_issue_label_test.go
similarity index 99%
rename from integrations/api_issue_label_test.go
rename to tests/integration/api_issue_label_test.go
index 9d9fdcfbc3..586c50a55f 100644
--- a/integrations/api_issue_label_test.go
+++ b/tests/integration/api_issue_label_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
diff --git a/integrations/api_issue_milestone_test.go b/tests/integration/api_issue_milestone_test.go
similarity index 97%
rename from integrations/api_issue_milestone_test.go
rename to tests/integration/api_issue_milestone_test.go
index ba97c99b9d..e22a091bb8 100644
--- a/integrations/api_issue_milestone_test.go
+++ b/tests/integration/api_issue_milestone_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -14,12 +14,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIIssuesMilestone(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	milestone := unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1})
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: milestone.RepoID})
diff --git a/integrations/api_issue_reaction_test.go b/tests/integration/api_issue_reaction_test.go
similarity index 97%
rename from integrations/api_issue_reaction_test.go
rename to tests/integration/api_issue_reaction_test.go
index ca6b69721c..a3cb9303fb 100644
--- a/integrations/api_issue_reaction_test.go
+++ b/tests/integration/api_issue_reaction_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -16,12 +16,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/convert"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIIssuesReactions(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
 	_ = issue.LoadRepo(db.DefaultContext)
@@ -78,7 +79,7 @@ func TestAPIIssuesReactions(t *testing.T) {
 }
 
 func TestAPICommentReactions(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 2})
 	_ = comment.LoadIssue()
diff --git a/integrations/api_issue_stopwatch_test.go b/tests/integration/api_issue_stopwatch_test.go
similarity index 95%
rename from integrations/api_issue_stopwatch_test.go
rename to tests/integration/api_issue_stopwatch_test.go
index 052a1ad9fc..c2ad9c45e8 100644
--- a/integrations/api_issue_stopwatch_test.go
+++ b/tests/integration/api_issue_stopwatch_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -14,12 +14,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIListStopWatches(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -43,7 +44,7 @@ func TestAPIListStopWatches(t *testing.T) {
 }
 
 func TestAPIStopStopWatches(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
 	_ = issue.LoadRepo(db.DefaultContext)
@@ -59,7 +60,7 @@ func TestAPIStopStopWatches(t *testing.T) {
 }
 
 func TestAPICancelStopWatches(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
 	_ = issue.LoadRepo(db.DefaultContext)
@@ -75,7 +76,7 @@ func TestAPICancelStopWatches(t *testing.T) {
 }
 
 func TestAPIStartStopWatches(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3})
 	_ = issue.LoadRepo(db.DefaultContext)
diff --git a/integrations/api_issue_subscription_test.go b/tests/integration/api_issue_subscription_test.go
similarity index 97%
rename from integrations/api_issue_subscription_test.go
rename to tests/integration/api_issue_subscription_test.go
index db3d1694d6..f4588fbbc4 100644
--- a/integrations/api_issue_subscription_test.go
+++ b/tests/integration/api_issue_subscription_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -14,12 +14,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIIssueSubscriptions(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	issue1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
 	issue2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
diff --git a/integrations/api_issue_test.go b/tests/integration/api_issue_test.go
similarity index 98%
rename from integrations/api_issue_test.go
rename to tests/integration/api_issue_test.go
index afb2f75c15..3e651c620b 100644
--- a/integrations/api_issue_test.go
+++ b/tests/integration/api_issue_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -18,12 +18,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIListIssues(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -73,7 +74,7 @@ func TestAPIListIssues(t *testing.T) {
 }
 
 func TestAPICreateIssue(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	const body, title = "apiTestBody", "apiTestTitle"
 
 	repoBefore := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
@@ -106,7 +107,7 @@ func TestAPICreateIssue(t *testing.T) {
 }
 
 func TestAPIEditIssue(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	issueBefore := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 10})
 	repoBefore := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issueBefore.RepoID})
@@ -168,7 +169,7 @@ func TestAPIEditIssue(t *testing.T) {
 }
 
 func TestAPISearchIssues(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	token := getUserToken(t, "user2")
 
@@ -268,7 +269,7 @@ func TestAPISearchIssues(t *testing.T) {
 }
 
 func TestAPISearchIssuesWithLabels(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// as this API was used in the frontend, it uses UI page size
 	expectedIssueCount := 15 // from the fixtures
diff --git a/integrations/api_issue_tracked_time_test.go b/tests/integration/api_issue_tracked_time_test.go
similarity index 97%
rename from integrations/api_issue_tracked_time_test.go
rename to tests/integration/api_issue_tracked_time_test.go
index 504aacf000..6e2c77030c 100644
--- a/integrations/api_issue_tracked_time_test.go
+++ b/tests/integration/api_issue_tracked_time_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -15,12 +15,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIGetTrackedTimes(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	issue2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
@@ -62,7 +63,7 @@ func TestAPIGetTrackedTimes(t *testing.T) {
 }
 
 func TestAPIDeleteTrackedTime(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	time6 := unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{ID: 6})
 	issue2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
@@ -97,7 +98,7 @@ func TestAPIDeleteTrackedTime(t *testing.T) {
 }
 
 func TestAPIAddTrackedTimes(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	issue2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
 	assert.NoError(t, issue2.LoadRepo(db.DefaultContext))
diff --git a/integrations/api_keys_test.go b/tests/integration/api_keys_test.go
similarity index 96%
rename from integrations/api_keys_test.go
rename to tests/integration/api_keys_test.go
index 76d1122086..1cb0b20ffe 100644
--- a/integrations/api_keys_test.go
+++ b/tests/integration/api_keys_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -16,18 +16,19 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestViewDeployKeysNoLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/keys")
 	MakeRequest(t, req, http.StatusUnauthorized)
 }
 
 func TestCreateDeployKeyNoLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/keys", api.CreateKeyOption{
 		Title: "title",
 		Key:   "key",
@@ -36,19 +37,19 @@ func TestCreateDeployKeyNoLogin(t *testing.T) {
 }
 
 func TestGetDeployKeyNoLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/keys/1")
 	MakeRequest(t, req, http.StatusUnauthorized)
 }
 
 func TestDeleteDeployKeyNoLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequest(t, "DELETE", "/api/v1/repos/user2/repo1/keys/1")
 	MakeRequest(t, req, http.StatusUnauthorized)
 }
 
 func TestCreateReadOnlyDeployKey(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: "repo1"})
 	repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
 
@@ -74,7 +75,7 @@ func TestCreateReadOnlyDeployKey(t *testing.T) {
 }
 
 func TestCreateReadWriteDeployKey(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: "repo1"})
 	repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
 
@@ -99,7 +100,7 @@ func TestCreateReadWriteDeployKey(t *testing.T) {
 }
 
 func TestCreateUserKey(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
 
 	session := loginUser(t, "user1")
diff --git a/integrations/api_nodeinfo_test.go b/tests/integration/api_nodeinfo_test.go
similarity index 98%
rename from integrations/api_nodeinfo_test.go
rename to tests/integration/api_nodeinfo_test.go
index bbb7912078..76f9105a51 100644
--- a/integrations/api_nodeinfo_test.go
+++ b/tests/integration/api_nodeinfo_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"context"
diff --git a/integrations/api_notification_test.go b/tests/integration/api_notification_test.go
similarity index 98%
rename from integrations/api_notification_test.go
rename to tests/integration/api_notification_test.go
index bd28f49851..bf85520bb5 100644
--- a/integrations/api_notification_test.go
+++ b/tests/integration/api_notification_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -14,12 +14,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPINotification(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
@@ -138,7 +139,7 @@ func TestAPINotification(t *testing.T) {
 }
 
 func TestAPINotificationPUT(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
diff --git a/integrations/api_oauth2_apps_test.go b/tests/integration/api_oauth2_apps_test.go
similarity index 98%
rename from integrations/api_oauth2_apps_test.go
rename to tests/integration/api_oauth2_apps_test.go
index 4eead582d1..fe3525724e 100644
--- a/integrations/api_oauth2_apps_test.go
+++ b/tests/integration/api_oauth2_apps_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.package models
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -13,12 +13,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestOAuth2Application(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testAPICreateOAuth2Application(t)
 	testAPIListOAuth2Applications(t)
 	testAPIGetOAuth2Application(t)
diff --git a/integrations/api_org_test.go b/tests/integration/api_org_test.go
similarity index 98%
rename from integrations/api_org_test.go
rename to tests/integration/api_org_test.go
index a3c1827e70..70bb17bee2 100644
--- a/integrations/api_org_test.go
+++ b/tests/integration/api_org_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -14,6 +14,7 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -138,7 +139,7 @@ func TestAPIOrgDeny(t *testing.T) {
 }
 
 func TestAPIGetAll(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequestf(t, "GET", "/api/v1/orgs")
 	resp := MakeRequest(t, req, http.StatusOK)
diff --git a/integrations/api_packages_composer_test.go b/tests/integration/api_packages_composer_test.go
similarity index 95%
rename from integrations/api_packages_composer_test.go
rename to tests/integration/api_packages_composer_test.go
index 7c58ae62be..90285f78d3 100644
--- a/integrations/api_packages_composer_test.go
+++ b/tests/integration/api_packages_composer_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"archive/zip"
@@ -19,12 +19,13 @@ import (
 	composer_module "code.gitea.io/gitea/modules/packages/composer"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/routers/api/packages/composer"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPackageComposer(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	vendorName := "gitea"
@@ -56,7 +57,7 @@ func TestPackageComposer(t *testing.T) {
 	url := fmt.Sprintf("%sapi/packages/%s/composer", setting.AppURL, user.Name)
 
 	t.Run("ServiceIndex", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/packages.json", url))
 		req = AddBasicAuthHeader(req, user.Name)
@@ -72,7 +73,7 @@ func TestPackageComposer(t *testing.T) {
 
 	t.Run("Upload", func(t *testing.T) {
 		t.Run("MissingVersion", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(content))
 			req = AddBasicAuthHeader(req, user.Name)
@@ -80,7 +81,7 @@ func TestPackageComposer(t *testing.T) {
 		})
 
 		t.Run("Valid", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			uploadURL := url + "?version=" + packageVersion
 
@@ -116,7 +117,7 @@ func TestPackageComposer(t *testing.T) {
 	})
 
 	t.Run("Download", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeComposer)
 		assert.NoError(t, err)
@@ -140,7 +141,7 @@ func TestPackageComposer(t *testing.T) {
 	})
 
 	t.Run("SearchService", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		cases := []struct {
 			Query           string
@@ -174,7 +175,7 @@ func TestPackageComposer(t *testing.T) {
 	})
 
 	t.Run("EnumeratePackages", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", url+"/list.json")
 		req = AddBasicAuthHeader(req, user.Name)
@@ -190,7 +191,7 @@ func TestPackageComposer(t *testing.T) {
 	})
 
 	t.Run("PackageMetadata", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/p2/%s/%s.json", url, vendorName, projectName))
 		req = AddBasicAuthHeader(req, user.Name)
diff --git a/integrations/api_packages_conan_test.go b/tests/integration/api_packages_conan_test.go
similarity index 96%
rename from integrations/api_packages_conan_test.go
rename to tests/integration/api_packages_conan_test.go
index e14555d1d0..5b34417343 100644
--- a/integrations/api_packages_conan_test.go
+++ b/tests/integration/api_packages_conan_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -20,6 +20,7 @@ import (
 	conan_module "code.gitea.io/gitea/modules/packages/conan"
 	"code.gitea.io/gitea/modules/setting"
 	conan_router "code.gitea.io/gitea/routers/api/packages/conan"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -204,7 +205,7 @@ func uploadConanPackageV2(t *testing.T, baseURL, token, name, version, user, cha
 }
 
 func TestPackageConan(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	name := "ConanPackage"
@@ -221,7 +222,7 @@ func TestPackageConan(t *testing.T) {
 
 	t.Run("v1", func(t *testing.T) {
 		t.Run("Ping", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/ping", url))
 			resp := MakeRequest(t, req, http.StatusOK)
@@ -232,7 +233,7 @@ func TestPackageConan(t *testing.T) {
 		token := ""
 
 		t.Run("Authenticate", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/users/authenticate", url))
 			req = AddBasicAuthHeader(req, user.Name)
@@ -245,7 +246,7 @@ func TestPackageConan(t *testing.T) {
 		})
 
 		t.Run("CheckCredentials", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/users/check_credentials", url))
 			req = addTokenAuthHeader(req, token)
@@ -253,12 +254,12 @@ func TestPackageConan(t *testing.T) {
 		})
 
 		t.Run("Upload", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			uploadConanPackageV1(t, url, token, name, version1, user1, channel1)
 
 			t.Run("Validate", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeConan)
 				assert.NoError(t, err)
@@ -302,7 +303,7 @@ func TestPackageConan(t *testing.T) {
 		})
 
 		t.Run("Download", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			recipeURL := fmt.Sprintf("%s/v1/conans/%s/%s/%s/%s", url, name, version1, user1, channel1)
 
@@ -368,7 +369,7 @@ func TestPackageConan(t *testing.T) {
 			uploadConanPackageV1(t, url, token, name, version1, user2, channel2)
 
 			t.Run("Recipe", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				cases := []struct {
 					Query    string
@@ -405,7 +406,7 @@ func TestPackageConan(t *testing.T) {
 			})
 
 			t.Run("Package", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/conans/%s/%s/%s/%s/search", url, name, version1, user1, channel2))
 				resp := MakeRequest(t, req, http.StatusOK)
@@ -421,7 +422,7 @@ func TestPackageConan(t *testing.T) {
 
 		t.Run("Delete", func(t *testing.T) {
 			t.Run("Package", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				cases := []struct {
 					Channel    string
@@ -450,7 +451,7 @@ func TestPackageConan(t *testing.T) {
 			})
 
 			t.Run("Recipe", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				cases := []struct {
 					Channel string
@@ -479,7 +480,7 @@ func TestPackageConan(t *testing.T) {
 
 	t.Run("v2", func(t *testing.T) {
 		t.Run("Ping", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/ping", url))
 			resp := MakeRequest(t, req, http.StatusOK)
@@ -490,7 +491,7 @@ func TestPackageConan(t *testing.T) {
 		token := ""
 
 		t.Run("Authenticate", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/users/authenticate", url))
 			req = AddBasicAuthHeader(req, user.Name)
@@ -503,7 +504,7 @@ func TestPackageConan(t *testing.T) {
 		})
 
 		t.Run("CheckCredentials", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/users/check_credentials", url))
 			req = addTokenAuthHeader(req, token)
@@ -511,12 +512,12 @@ func TestPackageConan(t *testing.T) {
 		})
 
 		t.Run("Upload", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			uploadConanPackageV2(t, url, token, name, version1, user1, channel1, revision1, revision1)
 
 			t.Run("Validate", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeConan)
 				assert.NoError(t, err)
@@ -525,7 +526,7 @@ func TestPackageConan(t *testing.T) {
 		})
 
 		t.Run("Latest", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			recipeURL := fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s", url, name, version1, user1, channel1)
 
@@ -547,7 +548,7 @@ func TestPackageConan(t *testing.T) {
 		})
 
 		t.Run("ListRevisions", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			uploadConanPackageV2(t, url, token, name, version1, user1, channel1, revision1, revision2)
 			uploadConanPackageV2(t, url, token, name, version1, user1, channel1, revision2, revision1)
@@ -590,7 +591,7 @@ func TestPackageConan(t *testing.T) {
 
 		t.Run("Search", func(t *testing.T) {
 			t.Run("Recipe", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				cases := []struct {
 					Query    string
@@ -627,7 +628,7 @@ func TestPackageConan(t *testing.T) {
 			})
 
 			t.Run("Package", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s/search", url, name, version1, user1, channel1))
 				resp := MakeRequest(t, req, http.StatusOK)
@@ -653,7 +654,7 @@ func TestPackageConan(t *testing.T) {
 
 		t.Run("Delete", func(t *testing.T) {
 			t.Run("Package", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				rref, _ := conan_module.NewRecipeReference(name, version1, user1, channel1, revision1)
 				pref, _ := conan_module.NewPackageReference(rref, conanPackageReference, conan_module.DefaultRevision)
@@ -695,7 +696,7 @@ func TestPackageConan(t *testing.T) {
 			})
 
 			t.Run("Recipe", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				rref, _ := conan_module.NewRecipeReference(name, version1, user1, channel1, conan_module.DefaultRevision)
 
diff --git a/integrations/api_packages_container_test.go b/tests/integration/api_packages_container_test.go
similarity index 96%
rename from integrations/api_packages_container_test.go
rename to tests/integration/api_packages_container_test.go
index c62ab5dbb8..adced5d661 100644
--- a/integrations/api_packages_container_test.go
+++ b/tests/integration/api_packages_container_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
@@ -21,12 +21,13 @@ import (
 	"code.gitea.io/gitea/modules/packages/container/oci"
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPackageContainer(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
@@ -80,7 +81,7 @@ func TestPackageContainer(t *testing.T) {
 		authenticate := []string{`Bearer realm="` + setting.AppURL + `v2/token",service="container_registry",scope="*"`}
 
 		t.Run("Anonymous", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL))
 			resp := MakeRequest(t, req, http.StatusUnauthorized)
@@ -103,7 +104,7 @@ func TestPackageContainer(t *testing.T) {
 		})
 
 		t.Run("User", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL))
 			resp := MakeRequest(t, req, http.StatusUnauthorized)
@@ -128,7 +129,7 @@ func TestPackageContainer(t *testing.T) {
 	})
 
 	t.Run("DetermineSupport", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%sv2", setting.AppURL))
 		addTokenAuthHeader(req, userToken)
@@ -141,7 +142,7 @@ func TestPackageContainer(t *testing.T) {
 			url := fmt.Sprintf("%sv2/%s/%s", setting.AppURL, user.Name, image)
 
 			t.Run("UploadBlob/Monolithic", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				req := NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads", url))
 				addTokenAuthHeader(req, anonymousToken)
@@ -171,7 +172,7 @@ func TestPackageContainer(t *testing.T) {
 			})
 
 			t.Run("UploadBlob/Chunked", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				req := NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads", url))
 				addTokenAuthHeader(req, userToken)
@@ -221,7 +222,7 @@ func TestPackageContainer(t *testing.T) {
 			for _, tag := range tags {
 				t.Run(fmt.Sprintf("[Tag:%s]", tag), func(t *testing.T) {
 					t.Run("UploadManifest", func(t *testing.T) {
-						defer PrintCurrentTest(t)()
+						defer tests.PrintCurrentTest(t)()
 
 						req := NewRequestWithBody(t, "POST", fmt.Sprintf("%s/blobs/uploads?digest=%s", url, configDigest), strings.NewReader(configContent))
 						addTokenAuthHeader(req, userToken)
@@ -296,7 +297,7 @@ func TestPackageContainer(t *testing.T) {
 					})
 
 					t.Run("HeadManifest", func(t *testing.T) {
-						defer PrintCurrentTest(t)()
+						defer tests.PrintCurrentTest(t)()
 
 						req := NewRequest(t, "HEAD", fmt.Sprintf("%s/manifests/unknown-tag", url))
 						addTokenAuthHeader(req, userToken)
@@ -311,7 +312,7 @@ func TestPackageContainer(t *testing.T) {
 					})
 
 					t.Run("GetManifest", func(t *testing.T) {
-						defer PrintCurrentTest(t)()
+						defer tests.PrintCurrentTest(t)()
 
 						req := NewRequest(t, "GET", fmt.Sprintf("%s/manifests/unknown-tag", url))
 						addTokenAuthHeader(req, userToken)
@@ -330,7 +331,7 @@ func TestPackageContainer(t *testing.T) {
 			}
 
 			t.Run("UploadUntaggedManifest", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				req := NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/manifests/%s", url, untaggedManifestDigest), strings.NewReader(untaggedManifestContent))
 				addTokenAuthHeader(req, userToken)
@@ -370,7 +371,7 @@ func TestPackageContainer(t *testing.T) {
 			})
 
 			t.Run("UploadIndexManifest", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				req := NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/manifests/%s", url, multiTag), strings.NewReader(indexManifestContent))
 				addTokenAuthHeader(req, userToken)
@@ -407,7 +408,7 @@ func TestPackageContainer(t *testing.T) {
 			})
 
 			t.Run("UploadBlob/Mount", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				req := NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads?mount=%s", url, unknownDigest))
 				addTokenAuthHeader(req, userToken)
@@ -422,7 +423,7 @@ func TestPackageContainer(t *testing.T) {
 			})
 
 			t.Run("HeadBlob", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				req := NewRequest(t, "HEAD", fmt.Sprintf("%s/blobs/%s", url, unknownDigest))
 				addTokenAuthHeader(req, userToken)
@@ -437,7 +438,7 @@ func TestPackageContainer(t *testing.T) {
 			})
 
 			t.Run("GetBlob", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				req := NewRequest(t, "GET", fmt.Sprintf("%s/blobs/%s", url, unknownDigest))
 				addTokenAuthHeader(req, userToken)
@@ -453,7 +454,7 @@ func TestPackageContainer(t *testing.T) {
 			})
 
 			t.Run("GetTagList", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				cases := []struct {
 					URL          string
@@ -515,7 +516,7 @@ func TestPackageContainer(t *testing.T) {
 
 			t.Run("Delete", func(t *testing.T) {
 				t.Run("Blob", func(t *testing.T) {
-					defer PrintCurrentTest(t)()
+					defer tests.PrintCurrentTest(t)()
 
 					req := NewRequest(t, "DELETE", fmt.Sprintf("%s/blobs/%s", url, blobDigest))
 					addTokenAuthHeader(req, userToken)
@@ -527,7 +528,7 @@ func TestPackageContainer(t *testing.T) {
 				})
 
 				t.Run("ManifestByDigest", func(t *testing.T) {
-					defer PrintCurrentTest(t)()
+					defer tests.PrintCurrentTest(t)()
 
 					req := NewRequest(t, "DELETE", fmt.Sprintf("%s/manifests/%s", url, untaggedManifestDigest))
 					addTokenAuthHeader(req, userToken)
@@ -539,7 +540,7 @@ func TestPackageContainer(t *testing.T) {
 				})
 
 				t.Run("ManifestByTag", func(t *testing.T) {
-					defer PrintCurrentTest(t)()
+					defer tests.PrintCurrentTest(t)()
 
 					req := NewRequest(t, "DELETE", fmt.Sprintf("%s/manifests/%s", url, multiTag))
 					addTokenAuthHeader(req, userToken)
@@ -554,11 +555,11 @@ func TestPackageContainer(t *testing.T) {
 	}
 
 	t.Run("OwnerNameChange", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		checkCatalog := func(owner string) func(t *testing.T) {
 			return func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrepareTestEnv(t)()
 
 				req := NewRequest(t, "GET", fmt.Sprintf("%sv2/_catalog", setting.AppURL))
 				addTokenAuthHeader(req, userToken)
diff --git a/integrations/api_packages_generic_test.go b/tests/integration/api_packages_generic_test.go
similarity index 92%
rename from integrations/api_packages_generic_test.go
rename to tests/integration/api_packages_generic_test.go
index f2aff8ed24..9fcd2cc797 100644
--- a/integrations/api_packages_generic_test.go
+++ b/tests/integration/api_packages_generic_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
@@ -14,12 +14,13 @@ import (
 	"code.gitea.io/gitea/models/packages"
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPackageGeneric(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	packageName := "te-st_pac.kage"
@@ -30,7 +31,7 @@ func TestPackageGeneric(t *testing.T) {
 	url := fmt.Sprintf("/api/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)
 
 	t.Run("Upload", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequestWithBody(t, "PUT", url+"/"+filename, bytes.NewReader(content))
 		AddBasicAuthHeader(req, user.Name)
@@ -57,7 +58,7 @@ func TestPackageGeneric(t *testing.T) {
 		assert.Equal(t, int64(len(content)), pb.Size)
 
 		t.Run("Exists", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequestWithBody(t, "PUT", url+"/"+filename, bytes.NewReader(content))
 			AddBasicAuthHeader(req, user.Name)
@@ -65,7 +66,7 @@ func TestPackageGeneric(t *testing.T) {
 		})
 
 		t.Run("Additional", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequestWithBody(t, "PUT", url+"/dummy.bin", bytes.NewReader(content))
 			AddBasicAuthHeader(req, user.Name)
@@ -79,7 +80,7 @@ func TestPackageGeneric(t *testing.T) {
 		})
 
 		t.Run("InvalidParameter", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequestWithBody(t, "PUT", fmt.Sprintf("/api/packages/%s/generic/%s/%s/%s", user.Name, "invalid+package name", packageVersion, filename), bytes.NewReader(content))
 			AddBasicAuthHeader(req, user.Name)
@@ -96,7 +97,7 @@ func TestPackageGeneric(t *testing.T) {
 	})
 
 	t.Run("Download", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		checkDownloadCount := func(count int64) {
 			pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeGeneric)
@@ -120,7 +121,7 @@ func TestPackageGeneric(t *testing.T) {
 		checkDownloadCount(2)
 
 		t.Run("NotExists", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", url+"/not.found")
 			MakeRequest(t, req, http.StatusNotFound)
@@ -128,10 +129,10 @@ func TestPackageGeneric(t *testing.T) {
 	})
 
 	t.Run("Delete", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		t.Run("File", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "DELETE", url+"/"+filename)
 			MakeRequest(t, req, http.StatusUnauthorized)
@@ -152,7 +153,7 @@ func TestPackageGeneric(t *testing.T) {
 			assert.Len(t, pvs, 1)
 
 			t.Run("RemovesVersion", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 
 				req = NewRequest(t, "DELETE", url+"/dummy.bin")
 				AddBasicAuthHeader(req, user.Name)
@@ -165,7 +166,7 @@ func TestPackageGeneric(t *testing.T) {
 		})
 
 		t.Run("Version", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequestWithBody(t, "PUT", url+"/"+filename, bytes.NewReader(content))
 			AddBasicAuthHeader(req, user.Name)
diff --git a/integrations/api_packages_helm_test.go b/tests/integration/api_packages_helm_test.go
similarity index 96%
rename from integrations/api_packages_helm_test.go
rename to tests/integration/api_packages_helm_test.go
index 8ea5e8a7b0..393bf3cbe2 100644
--- a/integrations/api_packages_helm_test.go
+++ b/tests/integration/api_packages_helm_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"archive/tar"
@@ -19,13 +19,14 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	helm_module "code.gitea.io/gitea/modules/packages/helm"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 	"gopkg.in/yaml.v2"
 )
 
 func TestPackageHelm(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	packageName := "test-chart"
@@ -63,7 +64,7 @@ dependencies:
 	url := fmt.Sprintf("/api/packages/%s/helm", user.Name)
 
 	t.Run("Upload", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		uploadURL := url + "/api/charts"
 
@@ -98,7 +99,7 @@ dependencies:
 	})
 
 	t.Run("Download", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		checkDownloadCount := func(count int64) {
 			pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeHelm)
@@ -119,7 +120,7 @@ dependencies:
 	})
 
 	t.Run("Index", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/index.yaml", url))
 		req = AddBasicAuthHeader(req, user.Name)
diff --git a/integrations/api_packages_maven_test.go b/tests/integration/api_packages_maven_test.go
similarity index 94%
rename from integrations/api_packages_maven_test.go
rename to tests/integration/api_packages_maven_test.go
index 512039b6a5..87d95557ce 100644
--- a/integrations/api_packages_maven_test.go
+++ b/tests/integration/api_packages_maven_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -15,12 +15,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/packages/maven"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPackageMaven(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	groupID := "com.gitea"
@@ -39,7 +40,7 @@ func TestPackageMaven(t *testing.T) {
 	}
 
 	t.Run("Upload", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		putFile(t, fmt.Sprintf("/%s/%s", packageVersion, filename), "test", http.StatusCreated)
 		putFile(t, fmt.Sprintf("/%s/%s", packageVersion, filename), "test", http.StatusBadRequest)
@@ -68,13 +69,13 @@ func TestPackageMaven(t *testing.T) {
 	})
 
 	t.Run("UploadExists", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		putFile(t, fmt.Sprintf("/%s/%s", packageVersion, filename), "test", http.StatusBadRequest)
 	})
 
 	t.Run("Download", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s", root, packageVersion, filename))
 		req = AddBasicAuthHeader(req, user.Name)
@@ -89,15 +90,15 @@ func TestPackageMaven(t *testing.T) {
 	})
 
 	t.Run("UploadVerifySHA1", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		t.Run("Missmatch", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			putFile(t, fmt.Sprintf("/%s/%s.sha1", packageVersion, filename), "test", http.StatusBadRequest)
 		})
 		t.Run("Valid", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			putFile(t, fmt.Sprintf("/%s/%s.sha1", packageVersion, filename), "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", http.StatusOK)
 		})
@@ -112,7 +113,7 @@ func TestPackageMaven(t *testing.T) {
 </project>`
 
 	t.Run("UploadPOM", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeMaven)
 		assert.NoError(t, err)
@@ -147,7 +148,7 @@ func TestPackageMaven(t *testing.T) {
 	})
 
 	t.Run("DownloadPOM", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s.pom", root, packageVersion, filename))
 		req = AddBasicAuthHeader(req, user.Name)
@@ -162,7 +163,7 @@ func TestPackageMaven(t *testing.T) {
 	})
 
 	t.Run("DownloadChecksums", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/1.2.3/%s", root, filename))
 		req = AddBasicAuthHeader(req, user.Name)
@@ -183,7 +184,7 @@ func TestPackageMaven(t *testing.T) {
 	})
 
 	t.Run("DownloadMetadata", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", root+"/maven-metadata.xml")
 		req = AddBasicAuthHeader(req, user.Name)
diff --git a/integrations/api_packages_npm_test.go b/tests/integration/api_packages_npm_test.go
similarity index 95%
rename from integrations/api_packages_npm_test.go
rename to tests/integration/api_packages_npm_test.go
index 8b22ead6d9..fe6cea1cb6 100644
--- a/integrations/api_packages_npm_test.go
+++ b/tests/integration/api_packages_npm_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"encoding/base64"
@@ -18,12 +18,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/packages/npm"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPackageNpm(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	token := fmt.Sprintf("Bearer %s", getTokenForLoggedInUser(t, loginUser(t, user.Name)))
@@ -72,7 +73,7 @@ func TestPackageNpm(t *testing.T) {
 	filename := fmt.Sprintf("%s-%s.tgz", strings.Split(packageName, "/")[1], packageVersion)
 
 	t.Run("Upload", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequestWithBody(t, "PUT", root, strings.NewReader(buildUpload(packageVersion)))
 		req = addTokenAuthHeader(req, token)
@@ -104,7 +105,7 @@ func TestPackageNpm(t *testing.T) {
 	})
 
 	t.Run("UploadExists", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequestWithBody(t, "PUT", root, strings.NewReader(buildUpload(packageVersion)))
 		req = addTokenAuthHeader(req, token)
@@ -112,7 +113,7 @@ func TestPackageNpm(t *testing.T) {
 	})
 
 	t.Run("Download", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/-/%s/%s", root, packageVersion, filename))
 		req = addTokenAuthHeader(req, token)
@@ -128,7 +129,7 @@ func TestPackageNpm(t *testing.T) {
 	})
 
 	t.Run("PackageMetadata", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("/api/packages/%s/npm/%s", user.Name, "does-not-exist"))
 		req = addTokenAuthHeader(req, token)
@@ -159,7 +160,7 @@ func TestPackageNpm(t *testing.T) {
 	})
 
 	t.Run("AddTag", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		test := func(t *testing.T, status int, tag, version string) {
 			req := NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/%s", tagsRoot, tag), strings.NewReader(`"`+version+`"`))
@@ -175,7 +176,7 @@ func TestPackageNpm(t *testing.T) {
 	})
 
 	t.Run("ListTags", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", tagsRoot)
 		req = addTokenAuthHeader(req, token)
@@ -192,7 +193,7 @@ func TestPackageNpm(t *testing.T) {
 	})
 
 	t.Run("PackageMetadataDistTags", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", root)
 		req = addTokenAuthHeader(req, token)
@@ -209,7 +210,7 @@ func TestPackageNpm(t *testing.T) {
 	})
 
 	t.Run("DeleteTag", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		test := func(t *testing.T, status int, tag string) {
 			req := NewRequest(t, "DELETE", fmt.Sprintf("%s/%s", tagsRoot, tag))
@@ -224,7 +225,7 @@ func TestPackageNpm(t *testing.T) {
 	})
 
 	t.Run("Delete", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequestWithBody(t, "PUT", root, strings.NewReader(buildUpload(packageVersion+"-dummy")))
 		req = addTokenAuthHeader(req, token)
@@ -238,7 +239,7 @@ func TestPackageNpm(t *testing.T) {
 		MakeRequest(t, req, http.StatusOK)
 
 		t.Run("Version", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeNpm)
 			assert.NoError(t, err)
@@ -257,7 +258,7 @@ func TestPackageNpm(t *testing.T) {
 		})
 
 		t.Run("Full", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeNpm)
 			assert.NoError(t, err)
diff --git a/integrations/api_packages_nuget_test.go b/tests/integration/api_packages_nuget_test.go
similarity index 96%
rename from integrations/api_packages_nuget_test.go
rename to tests/integration/api_packages_nuget_test.go
index 5b662309ea..87275feb3e 100644
--- a/integrations/api_packages_nuget_test.go
+++ b/tests/integration/api_packages_nuget_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"archive/zip"
@@ -20,6 +20,7 @@ import (
 	nuget_module "code.gitea.io/gitea/modules/packages/nuget"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/routers/api/packages/nuget"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -30,7 +31,7 @@ func addNuGetAPIKeyHeader(request *http.Request, token string) *http.Request {
 }
 
 func TestPackageNuGet(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	token := getUserToken(t, user.Name)
@@ -63,7 +64,7 @@ func TestPackageNuGet(t *testing.T) {
 	url := fmt.Sprintf("/api/packages/%s/nuget", user.Name)
 
 	t.Run("ServiceIndex", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/index.json", url))
 		req = AddBasicAuthHeader(req, user.Name)
@@ -104,7 +105,7 @@ func TestPackageNuGet(t *testing.T) {
 
 	t.Run("Upload", func(t *testing.T) {
 		t.Run("DependencyPackage", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(content))
 			req = AddBasicAuthHeader(req, user.Name)
@@ -137,7 +138,7 @@ func TestPackageNuGet(t *testing.T) {
 		})
 
 		t.Run("SymbolPackage", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			createPackage := func(id, packageType string) io.Reader {
 				var buf bytes.Buffer
@@ -224,7 +225,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
 	})
 
 	t.Run("Download", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		checkDownloadCount := func(count int64) {
 			pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeNuGet)
@@ -250,7 +251,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
 		checkDownloadCount(1)
 
 		t.Run("Symbol", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", fmt.Sprintf("%s/symbols/%s/%sFFFFFFFF/gitea.pdb", url, symbolFilename, symbolID))
 			MakeRequest(t, req, http.StatusBadRequest)
@@ -268,7 +269,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
 	})
 
 	t.Run("SearchService", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		cases := []struct {
 			Query           string
@@ -303,7 +304,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
 		contentURL := fmt.Sprintf("%s%s/package/%s/%s/%s.%s.nupkg", setting.AppURL, url[1:], packageName, packageVersion, packageName, packageVersion)
 
 		t.Run("RegistrationIndex", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", fmt.Sprintf("%s/registration/%s/index.json", url, packageName))
 			req = AddBasicAuthHeader(req, user.Name)
@@ -329,7 +330,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
 		})
 
 		t.Run("RegistrationLeaf", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := NewRequest(t, "GET", fmt.Sprintf("%s/registration/%s/%s.json", url, packageName, packageVersion))
 			req = AddBasicAuthHeader(req, user.Name)
@@ -345,7 +346,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
 	})
 
 	t.Run("PackageService", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/index.json", url, packageName))
 		req = AddBasicAuthHeader(req, user.Name)
@@ -359,7 +360,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
 	})
 
 	t.Run("Delete", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, packageName, packageVersion))
 		req = AddBasicAuthHeader(req, user.Name)
@@ -371,7 +372,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
 	})
 
 	t.Run("DownloadNotExists", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s.%s.nupkg", url, packageName, packageVersion, packageName, packageVersion))
 		req = AddBasicAuthHeader(req, user.Name)
@@ -383,7 +384,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
 	})
 
 	t.Run("DeleteNotExists", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "DELETE", fmt.Sprintf("%s/package/%s/%s", url, packageName, packageVersion))
 		req = AddBasicAuthHeader(req, user.Name)
diff --git a/integrations/api_packages_pub_test.go b/tests/integration/api_packages_pub_test.go
similarity index 96%
rename from integrations/api_packages_pub_test.go
rename to tests/integration/api_packages_pub_test.go
index 76d5116158..9e4ce63fa1 100644
--- a/integrations/api_packages_pub_test.go
+++ b/tests/integration/api_packages_pub_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"archive/tar"
@@ -21,12 +21,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	pub_module "code.gitea.io/gitea/modules/packages/pub"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPackagePub(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	token := "Bearer " + getUserToken(t, user.Name)
@@ -57,7 +58,7 @@ description: ` + packageDescription
 	root := fmt.Sprintf("/api/packages/%s/pub", user.Name)
 
 	t.Run("Upload", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		uploadURL := root + "/api/packages/versions/new"
 
@@ -123,7 +124,7 @@ description: ` + packageDescription
 	})
 
 	t.Run("Download", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/api/packages/%s/%s", root, packageName, packageVersion))
 		resp := MakeRequest(t, req, http.StatusOK)
@@ -148,7 +149,7 @@ description: ` + packageDescription
 	})
 
 	t.Run("EnumeratePackageVersions", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/api/packages/%s", root, packageName))
 		resp := MakeRequest(t, req, http.StatusOK)
diff --git a/integrations/api_packages_pypi_test.go b/tests/integration/api_packages_pypi_test.go
similarity index 94%
rename from integrations/api_packages_pypi_test.go
rename to tests/integration/api_packages_pypi_test.go
index a4c49ef101..32b3304ca7 100644
--- a/integrations/api_packages_pypi_test.go
+++ b/tests/integration/api_packages_pypi_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
@@ -19,12 +19,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/packages/pypi"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPackagePyPI(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	packageName := "test-package"
@@ -60,7 +61,7 @@ func TestPackagePyPI(t *testing.T) {
 	}
 
 	t.Run("Upload", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		filename := "test.whl"
 		uploadFile(t, filename, content, http.StatusCreated)
@@ -88,7 +89,7 @@ func TestPackagePyPI(t *testing.T) {
 	})
 
 	t.Run("UploadAddFile", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		filename := "test.tar.gz"
 		uploadFile(t, filename, content, http.StatusCreated)
@@ -119,21 +120,21 @@ func TestPackagePyPI(t *testing.T) {
 	})
 
 	t.Run("UploadHashMismatch", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		filename := "test2.whl"
 		uploadFile(t, filename, "dummy", http.StatusBadRequest)
 	})
 
 	t.Run("UploadExists", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		uploadFile(t, "test.whl", content, http.StatusBadRequest)
 		uploadFile(t, "test.tar.gz", content, http.StatusBadRequest)
 	})
 
 	t.Run("Download", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		downloadFile := func(filename string) {
 			req := NewRequest(t, "GET", fmt.Sprintf("%s/files/%s/%s/%s", root, packageName, packageVersion, filename))
@@ -153,7 +154,7 @@ func TestPackagePyPI(t *testing.T) {
 	})
 
 	t.Run("PackageMetadata", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/simple/%s", root, packageName))
 		req = AddBasicAuthHeader(req, user.Name)
diff --git a/integrations/api_packages_rubygems_test.go b/tests/integration/api_packages_rubygems_test.go
similarity index 97%
rename from integrations/api_packages_rubygems_test.go
rename to tests/integration/api_packages_rubygems_test.go
index 2228d3d0c1..6cf5af710b 100644
--- a/integrations/api_packages_rubygems_test.go
+++ b/tests/integration/api_packages_rubygems_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
@@ -17,12 +17,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/packages/rubygems"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPackageRubyGems(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	packageName := "gitea"
@@ -120,7 +121,7 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`)
 	}
 
 	t.Run("Upload", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		uploadFile(t, http.StatusCreated)
 
@@ -147,13 +148,13 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`)
 	})
 
 	t.Run("UploadExists", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		uploadFile(t, http.StatusBadRequest)
 	})
 
 	t.Run("Download", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/gems/%s", root, packageFilename))
 		req = AddBasicAuthHeader(req, user.Name)
@@ -168,7 +169,7 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`)
 	})
 
 	t.Run("DownloadGemspec", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/quick/Marshal.4.8/%sspec.rz", root, packageFilename))
 		req = AddBasicAuthHeader(req, user.Name)
@@ -187,7 +188,7 @@ gAAAAP//MS06Gw==`)
 	})
 
 	t.Run("EnumeratePackages", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		enumeratePackages := func(t *testing.T, endpoint string, expectedContent []byte) {
 			req := NewRequest(t, "GET", fmt.Sprintf("%s/%s", root, endpoint))
@@ -206,7 +207,7 @@ gAAAAP//MS06Gw==`)
 	})
 
 	t.Run("Delete", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		body := bytes.Buffer{}
 		writer := multipart.NewWriter(&body)
diff --git a/integrations/api_packages_test.go b/tests/integration/api_packages_test.go
similarity index 95%
rename from integrations/api_packages_test.go
rename to tests/integration/api_packages_test.go
index fcdacacea0..86d81994d4 100644
--- a/integrations/api_packages_test.go
+++ b/tests/integration/api_packages_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
@@ -18,12 +18,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
 	packages_service "code.gitea.io/gitea/services/packages"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPackageAPI(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
 	session := loginUser(t, user.Name)
 	token := getTokenForLoggedInUser(t, session)
@@ -38,7 +39,7 @@ func TestPackageAPI(t *testing.T) {
 	MakeRequest(t, req, http.StatusCreated)
 
 	t.Run("ListPackages", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s?token=%s", user.Name, token))
 		resp := MakeRequest(t, req, http.StatusOK)
@@ -55,7 +56,7 @@ func TestPackageAPI(t *testing.T) {
 	})
 
 	t.Run("GetPackage", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/dummy/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
 		MakeRequest(t, req, http.StatusNotFound)
@@ -73,7 +74,7 @@ func TestPackageAPI(t *testing.T) {
 		assert.Equal(t, user.Name, p.Creator.UserName)
 
 		t.Run("RepositoryLink", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			p, err := packages_model.GetPackageByName(db.DefaultContext, user.ID, packages_model.TypeGeneric, packageName)
 			assert.NoError(t, err)
@@ -112,7 +113,7 @@ func TestPackageAPI(t *testing.T) {
 	})
 
 	t.Run("ListPackageFiles", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/dummy/%s/%s/files?token=%s", user.Name, packageName, packageVersion, token))
 		MakeRequest(t, req, http.StatusNotFound)
@@ -133,7 +134,7 @@ func TestPackageAPI(t *testing.T) {
 	})
 
 	t.Run("DeletePackage", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/packages/%s/dummy/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
 		MakeRequest(t, req, http.StatusNotFound)
@@ -144,7 +145,7 @@ func TestPackageAPI(t *testing.T) {
 }
 
 func TestPackageCleanup(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	time.Sleep(time.Second)
 
diff --git a/integrations/api_packages_vagrant_test.go b/tests/integration/api_packages_vagrant_test.go
similarity index 95%
rename from integrations/api_packages_vagrant_test.go
rename to tests/integration/api_packages_vagrant_test.go
index 8ce4f24ef5..1d2952e1a2 100644
--- a/integrations/api_packages_vagrant_test.go
+++ b/tests/integration/api_packages_vagrant_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"archive/tar"
@@ -19,12 +19,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/json"
 	vagrant_module "code.gitea.io/gitea/modules/packages/vagrant"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPackageVagrant(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	token := "Bearer " + getUserToken(t, user.Name)
@@ -56,7 +57,7 @@ func TestPackageVagrant(t *testing.T) {
 	root := fmt.Sprintf("/api/packages/%s/vagrant", user.Name)
 
 	t.Run("Authenticate", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		authenticateURL := fmt.Sprintf("%s/authenticate", root)
 
@@ -71,7 +72,7 @@ func TestPackageVagrant(t *testing.T) {
 	boxURL := fmt.Sprintf("%s/%s", root, packageName)
 
 	t.Run("Upload", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "HEAD", boxURL)
 		MakeRequest(t, req, http.StatusNotFound)
@@ -116,7 +117,7 @@ func TestPackageVagrant(t *testing.T) {
 	})
 
 	t.Run("Download", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s", boxURL, packageVersion, filename))
 		resp := MakeRequest(t, req, http.StatusOK)
@@ -125,7 +126,7 @@ func TestPackageVagrant(t *testing.T) {
 	})
 
 	t.Run("EnumeratePackageVersions", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", boxURL)
 		resp := MakeRequest(t, req, http.StatusOK)
diff --git a/integrations/api_private_serv_test.go b/tests/integration/api_private_serv_test.go
similarity index 99%
rename from integrations/api_private_serv_test.go
rename to tests/integration/api_private_serv_test.go
index fd3cb25ef2..6fd6d616db 100644
--- a/integrations/api_private_serv_test.go
+++ b/tests/integration/api_private_serv_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"context"
diff --git a/integrations/api_pull_commits_test.go b/tests/integration/api_pull_commits_test.go
similarity index 93%
rename from integrations/api_pull_commits_test.go
rename to tests/integration/api_pull_commits_test.go
index 693011c235..aa58f44bbe 100644
--- a/integrations/api_pull_commits_test.go
+++ b/tests/integration/api_pull_commits_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -12,12 +12,13 @@ import (
 	repo_model "code.gitea.io/gitea/models/repo"
 	"code.gitea.io/gitea/models/unittest"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIPullCommits(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	pullIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
 	assert.NoError(t, pullIssue.LoadIssue())
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: pullIssue.HeadRepoID})
diff --git a/integrations/api_pull_review_test.go b/tests/integration/api_pull_review_test.go
similarity index 99%
rename from integrations/api_pull_review_test.go
rename to tests/integration/api_pull_review_test.go
index 024ead9050..6ebad106fb 100644
--- a/integrations/api_pull_review_test.go
+++ b/tests/integration/api_pull_review_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -15,12 +15,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	"code.gitea.io/gitea/modules/json"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIPullReview(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	pullIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3})
 	assert.NoError(t, pullIssue.LoadAttributes(db.DefaultContext))
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: pullIssue.RepoID})
@@ -223,7 +224,7 @@ func TestAPIPullReview(t *testing.T) {
 }
 
 func TestAPIPullReviewRequest(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	pullIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3})
 	assert.NoError(t, pullIssue.LoadAttributes(db.DefaultContext))
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: pullIssue.RepoID})
diff --git a/integrations/api_pull_test.go b/tests/integration/api_pull_test.go
similarity index 96%
rename from integrations/api_pull_test.go
rename to tests/integration/api_pull_test.go
index 4cb1b43cbb..032912a073 100644
--- a/integrations/api_pull_test.go
+++ b/tests/integration/api_pull_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -17,12 +17,13 @@ import (
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/services/forms"
 	issue_service "code.gitea.io/gitea/services/issue"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIViewPulls(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
 
@@ -39,7 +40,7 @@ func TestAPIViewPulls(t *testing.T) {
 
 // TestAPIMergePullWIP ensures that we can't merge a WIP pull request
 func TestAPIMergePullWIP(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
 	pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{Status: issues_model.PullRequestStatusMergeable}, unittest.Cond("has_merged = ?", false))
@@ -62,7 +63,7 @@ func TestAPIMergePullWIP(t *testing.T) {
 }
 
 func TestAPICreatePullSuccess(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	repo10 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
 	// repo10 have code, pulls units.
 	repo11 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 11})
@@ -82,7 +83,7 @@ func TestAPICreatePullSuccess(t *testing.T) {
 }
 
 func TestAPICreatePullWithFieldsSuccess(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	// repo10 have code, pulls units.
 	repo10 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
 	owner10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo10.OwnerID})
@@ -119,7 +120,7 @@ func TestAPICreatePullWithFieldsSuccess(t *testing.T) {
 }
 
 func TestAPICreatePullWithFieldsFailure(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	// repo10 have code, pulls units.
 	repo10 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
 	owner10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo10.OwnerID})
@@ -153,7 +154,7 @@ func TestAPICreatePullWithFieldsFailure(t *testing.T) {
 }
 
 func TestAPIEditPull(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	repo10 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
 	owner10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo10.OwnerID})
 
diff --git a/integrations/api_releases_test.go b/tests/integration/api_releases_test.go
similarity index 96%
rename from integrations/api_releases_test.go
rename to tests/integration/api_releases_test.go
index ef9390390d..0c7f5e2d52 100644
--- a/integrations/api_releases_test.go
+++ b/tests/integration/api_releases_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -15,12 +15,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/git"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIListReleases(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
@@ -95,7 +96,7 @@ func createNewReleaseUsingAPI(t *testing.T, session *TestSession, token string,
 }
 
 func TestAPICreateAndUpdateRelease(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -147,7 +148,7 @@ func TestAPICreateAndUpdateRelease(t *testing.T) {
 }
 
 func TestAPICreateReleaseToDefaultBranch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -158,7 +159,7 @@ func TestAPICreateReleaseToDefaultBranch(t *testing.T) {
 }
 
 func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -176,7 +177,7 @@ func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) {
 }
 
 func TestAPIGetReleaseByTag(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -209,7 +210,7 @@ func TestAPIGetReleaseByTag(t *testing.T) {
 }
 
 func TestAPIDeleteReleaseByTagName(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
diff --git a/integrations/api_repo_archive_test.go b/tests/integration/api_repo_archive_test.go
similarity index 95%
rename from integrations/api_repo_archive_test.go
rename to tests/integration/api_repo_archive_test.go
index ca959a1287..3707cb7c1c 100644
--- a/integrations/api_repo_archive_test.go
+++ b/tests/integration/api_repo_archive_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -14,12 +14,13 @@ import (
 	repo_model "code.gitea.io/gitea/models/repo"
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIDownloadArchive(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
diff --git a/integrations/api_repo_collaborator_test.go b/tests/integration/api_repo_collaborator_test.go
similarity index 99%
rename from integrations/api_repo_collaborator_test.go
rename to tests/integration/api_repo_collaborator_test.go
index f2e5bf648d..3527e16572 100644
--- a/integrations/api_repo_collaborator_test.go
+++ b/tests/integration/api_repo_collaborator_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
diff --git a/integrations/api_repo_edit_test.go b/tests/integration/api_repo_edit_test.go
similarity index 99%
rename from integrations/api_repo_edit_test.go
rename to tests/integration/api_repo_edit_test.go
index 677fc0beff..5ef92bf47c 100644
--- a/integrations/api_repo_edit_test.go
+++ b/tests/integration/api_repo_edit_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
diff --git a/integrations/api_repo_file_create_test.go b/tests/integration/api_repo_file_create_test.go
similarity index 99%
rename from integrations/api_repo_file_create_test.go
rename to tests/integration/api_repo_file_create_test.go
index f9ed479ca2..f03efaa0ea 100644
--- a/integrations/api_repo_file_create_test.go
+++ b/tests/integration/api_repo_file_create_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	stdCtx "context"
diff --git a/integrations/api_repo_file_delete_test.go b/tests/integration/api_repo_file_delete_test.go
similarity index 99%
rename from integrations/api_repo_file_delete_test.go
rename to tests/integration/api_repo_file_delete_test.go
index 340ffe362e..2c8b1e381f 100644
--- a/integrations/api_repo_file_delete_test.go
+++ b/tests/integration/api_repo_file_delete_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
diff --git a/integrations/api_repo_file_get_test.go b/tests/integration/api_repo_file_get_test.go
similarity index 95%
rename from integrations/api_repo_file_get_test.go
rename to tests/integration/api_repo_file_get_test.go
index 8d1c4c4bcf..2a7a5fa634 100644
--- a/integrations/api_repo_file_get_test.go
+++ b/tests/integration/api_repo_file_get_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -12,12 +12,13 @@ import (
 
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIGetRawFileOrLFS(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// Test with raw file
 	req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/media/README.md")
diff --git a/integrations/api_repo_file_helpers.go b/tests/integration/api_repo_file_helpers.go
similarity index 97%
rename from integrations/api_repo_file_helpers.go
rename to tests/integration/api_repo_file_helpers.go
index 465e03d53c..298bae95c0 100644
--- a/integrations/api_repo_file_helpers.go
+++ b/tests/integration/api_repo_file_helpers.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	repo_model "code.gitea.io/gitea/models/repo"
diff --git a/integrations/api_repo_file_update_test.go b/tests/integration/api_repo_file_update_test.go
similarity index 99%
rename from integrations/api_repo_file_update_test.go
rename to tests/integration/api_repo_file_update_test.go
index 3044f03844..a3be67ad84 100644
--- a/integrations/api_repo_file_update_test.go
+++ b/tests/integration/api_repo_file_update_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	stdCtx "context"
diff --git a/integrations/api_repo_get_contents_list_test.go b/tests/integration/api_repo_get_contents_list_test.go
similarity index 99%
rename from integrations/api_repo_get_contents_list_test.go
rename to tests/integration/api_repo_get_contents_list_test.go
index 18231a2caf..4f2f5cb528 100644
--- a/integrations/api_repo_get_contents_list_test.go
+++ b/tests/integration/api_repo_get_contents_list_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
diff --git a/integrations/api_repo_get_contents_test.go b/tests/integration/api_repo_get_contents_test.go
similarity index 99%
rename from integrations/api_repo_get_contents_test.go
rename to tests/integration/api_repo_get_contents_test.go
index 1fb8b9bf0d..dddc316e1a 100644
--- a/integrations/api_repo_get_contents_test.go
+++ b/tests/integration/api_repo_get_contents_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
diff --git a/integrations/api_repo_git_blobs_test.go b/tests/integration/api_repo_git_blobs_test.go
similarity index 97%
rename from integrations/api_repo_git_blobs_test.go
rename to tests/integration/api_repo_git_blobs_test.go
index 7b990450d8..cb5116c743 100644
--- a/integrations/api_repo_git_blobs_test.go
+++ b/tests/integration/api_repo_git_blobs_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -12,12 +12,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIReposGitBlobs(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})         // owner of the repo1 & repo16
 	user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})         // owner of the repo3
 	user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})         // owner of neither repos
diff --git a/integrations/api_repo_git_commits_test.go b/tests/integration/api_repo_git_commits_test.go
similarity index 95%
rename from integrations/api_repo_git_commits_test.go
rename to tests/integration/api_repo_git_commits_test.go
index 7eba5bd223..99f83f943c 100644
--- a/integrations/api_repo_git_commits_test.go
+++ b/tests/integration/api_repo_git_commits_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -11,6 +11,7 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -24,7 +25,7 @@ func compareCommitFiles(t *testing.T, expect []string, files []*api.CommitAffect
 }
 
 func TestAPIReposGitCommits(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	// Login as User2.
 	session := loginUser(t, user.Name)
@@ -52,7 +53,7 @@ func TestAPIReposGitCommits(t *testing.T) {
 }
 
 func TestAPIReposGitCommitList(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	// Login as User2.
 	session := loginUser(t, user.Name)
@@ -75,7 +76,7 @@ func TestAPIReposGitCommitList(t *testing.T) {
 }
 
 func TestAPIReposGitCommitListPage2Empty(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	// Login as User2.
 	session := loginUser(t, user.Name)
@@ -92,7 +93,7 @@ func TestAPIReposGitCommitListPage2Empty(t *testing.T) {
 }
 
 func TestAPIReposGitCommitListDifferentBranch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	// Login as User2.
 	session := loginUser(t, user.Name)
@@ -111,7 +112,7 @@ func TestAPIReposGitCommitListDifferentBranch(t *testing.T) {
 }
 
 func TestDownloadCommitDiffOrPatch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	// Login as User2.
 	session := loginUser(t, user.Name)
@@ -133,7 +134,7 @@ func TestDownloadCommitDiffOrPatch(t *testing.T) {
 }
 
 func TestGetFileHistory(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	// Login as User2.
 	session := loginUser(t, user.Name)
diff --git a/integrations/api_repo_git_hook_test.go b/tests/integration/api_repo_git_hook_test.go
similarity index 94%
rename from integrations/api_repo_git_hook_test.go
rename to tests/integration/api_repo_git_hook_test.go
index b90d66c175..a6c4f91d4a 100644
--- a/integrations/api_repo_git_hook_test.go
+++ b/tests/integration/api_repo_git_hook_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -13,6 +13,7 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -23,7 +24,7 @@ echo Hello, World!
 `
 
 func TestAPIListGitHooks(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 37})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -49,7 +50,7 @@ func TestAPIListGitHooks(t *testing.T) {
 }
 
 func TestAPIListGitHooksNoHooks(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -70,7 +71,7 @@ func TestAPIListGitHooksNoHooks(t *testing.T) {
 }
 
 func TestAPIListGitHooksNoAccess(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -83,7 +84,7 @@ func TestAPIListGitHooksNoAccess(t *testing.T) {
 }
 
 func TestAPIGetGitHook(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 37})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -101,7 +102,7 @@ func TestAPIGetGitHook(t *testing.T) {
 }
 
 func TestAPIGetGitHookNoAccess(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -114,7 +115,7 @@ func TestAPIGetGitHookNoAccess(t *testing.T) {
 }
 
 func TestAPIEditGitHook(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -144,7 +145,7 @@ func TestAPIEditGitHook(t *testing.T) {
 }
 
 func TestAPIEditGitHookNoAccess(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -160,7 +161,7 @@ func TestAPIEditGitHookNoAccess(t *testing.T) {
 }
 
 func TestAPIDeleteGitHook(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 37})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
@@ -183,7 +184,7 @@ func TestAPIDeleteGitHook(t *testing.T) {
 }
 
 func TestAPIDeleteGitHookNoAccess(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
diff --git a/integrations/api_repo_git_notes_test.go b/tests/integration/api_repo_git_notes_test.go
similarity index 98%
rename from integrations/api_repo_git_notes_test.go
rename to tests/integration/api_repo_git_notes_test.go
index 733e0575dc..713c7599c3 100644
--- a/integrations/api_repo_git_notes_test.go
+++ b/tests/integration/api_repo_git_notes_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
diff --git a/integrations/api_repo_git_ref_test.go b/tests/integration/api_repo_git_ref_test.go
similarity index 93%
rename from integrations/api_repo_git_ref_test.go
rename to tests/integration/api_repo_git_ref_test.go
index 7ff16eb1c5..e8fc47f8dc 100644
--- a/integrations/api_repo_git_ref_test.go
+++ b/tests/integration/api_repo_git_ref_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -10,10 +10,11 @@ import (
 
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 )
 
 func TestAPIReposGitRefs(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	// Login as User2.
 	session := loginUser(t, user.Name)
diff --git a/integrations/api_repo_git_tags_test.go b/tests/integration/api_repo_git_tags_test.go
similarity index 96%
rename from integrations/api_repo_git_tags_test.go
rename to tests/integration/api_repo_git_tags_test.go
index 45551a4d7b..855eb2451e 100644
--- a/integrations/api_repo_git_tags_test.go
+++ b/tests/integration/api_repo_git_tags_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -15,12 +15,13 @@ import (
 	"code.gitea.io/gitea/modules/git"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIGitTags(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	// Login as User2.
@@ -64,7 +65,7 @@ func TestAPIGitTags(t *testing.T) {
 }
 
 func TestAPIDeleteTagByName(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
diff --git a/integrations/api_repo_git_trees_test.go b/tests/integration/api_repo_git_trees_test.go
similarity index 97%
rename from integrations/api_repo_git_trees_test.go
rename to tests/integration/api_repo_git_trees_test.go
index d80bcadb69..385fec12ba 100644
--- a/integrations/api_repo_git_trees_test.go
+++ b/tests/integration/api_repo_git_trees_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -11,10 +11,11 @@ import (
 	repo_model "code.gitea.io/gitea/models/repo"
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 )
 
 func TestAPIReposGitTrees(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})         // owner of the repo1 & repo16
 	user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})         // owner of the repo3
 	user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})         // owner of neither repos
diff --git a/integrations/api_repo_languages_test.go b/tests/integration/api_repo_languages_test.go
similarity index 98%
rename from integrations/api_repo_languages_test.go
rename to tests/integration/api_repo_languages_test.go
index 8775d25029..98373fb6b1 100644
--- a/integrations/api_repo_languages_test.go
+++ b/tests/integration/api_repo_languages_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
diff --git a/integrations/api_repo_lfs_locks_test.go b/tests/integration/api_repo_lfs_locks_test.go
similarity index 98%
rename from integrations/api_repo_lfs_locks_test.go
rename to tests/integration/api_repo_lfs_locks_test.go
index 3fd8f48f97..0860f47533 100644
--- a/integrations/api_repo_lfs_locks_test.go
+++ b/tests/integration/api_repo_lfs_locks_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -16,12 +16,13 @@ import (
 	"code.gitea.io/gitea/modules/lfs"
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPILFSLocksNotStarted(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	setting.LFS.StartServer = false
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
@@ -37,7 +38,7 @@ func TestAPILFSLocksNotStarted(t *testing.T) {
 }
 
 func TestAPILFSLocksNotLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	setting.LFS.StartServer = true
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
@@ -51,7 +52,7 @@ func TestAPILFSLocksNotLogin(t *testing.T) {
 }
 
 func TestAPILFSLocksLogged(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	setting.LFS.StartServer = true
 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // in org 3
 	user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) // in org 3
diff --git a/integrations/api_repo_lfs_migrate_test.go b/tests/integration/api_repo_lfs_migrate_test.go
similarity index 95%
rename from integrations/api_repo_lfs_migrate_test.go
rename to tests/integration/api_repo_lfs_migrate_test.go
index 1f6893f32a..d2edf67e8b 100644
--- a/integrations/api_repo_lfs_migrate_test.go
+++ b/tests/integration/api_repo_lfs_migrate_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -15,12 +15,13 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/services/migrations"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIRepoLFSMigrateLocal(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	oldImportLocalPaths := setting.ImportLocalPaths
 	oldAllowLocalNetworks := setting.Migrations.AllowLocalNetworks
diff --git a/integrations/api_repo_lfs_test.go b/tests/integration/api_repo_lfs_test.go
similarity index 92%
rename from integrations/api_repo_lfs_test.go
rename to tests/integration/api_repo_lfs_test.go
index 8bbc019953..440dd04a81 100644
--- a/integrations/api_repo_lfs_test.go
+++ b/tests/integration/api_repo_lfs_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
@@ -19,12 +19,13 @@ import (
 	"code.gitea.io/gitea/modules/json"
 	"code.gitea.io/gitea/modules/lfs"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPILFSNotStarted(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	setting.LFS.StartServer = false
 
@@ -44,7 +45,7 @@ func TestAPILFSNotStarted(t *testing.T) {
 }
 
 func TestAPILFSMediaType(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	setting.LFS.StartServer = true
 
@@ -68,7 +69,7 @@ func createLFSTestRepository(t *testing.T, name string) *repo_model.Repository {
 }
 
 func TestAPILFSBatch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	setting.LFS.StartServer = true
 
@@ -94,7 +95,7 @@ func TestAPILFSBatch(t *testing.T) {
 	}
 
 	t.Run("InvalidJsonRequest", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, nil)
 
@@ -102,7 +103,7 @@ func TestAPILFSBatch(t *testing.T) {
 	})
 
 	t.Run("InvalidOperation", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, &lfs.BatchRequest{
 			Operation: "dummy",
@@ -112,7 +113,7 @@ func TestAPILFSBatch(t *testing.T) {
 	})
 
 	t.Run("InvalidPointer", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, &lfs.BatchRequest{
 			Operation: "download",
@@ -138,7 +139,7 @@ func TestAPILFSBatch(t *testing.T) {
 	})
 
 	t.Run("PointerSizeMismatch", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, &lfs.BatchRequest{
 			Operation: "download",
@@ -156,10 +157,10 @@ func TestAPILFSBatch(t *testing.T) {
 	})
 
 	t.Run("Download", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		t.Run("PointerNotInStore", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := newRequest(t, &lfs.BatchRequest{
 				Operation: "download",
@@ -176,7 +177,7 @@ func TestAPILFSBatch(t *testing.T) {
 		})
 
 		t.Run("MetaNotFound", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			p := lfs.Pointer{Oid: "05eeb4eb5be71f2dd291ca39157d6d9effd7d1ea19cbdc8a99411fe2a8f26a00", Size: 6}
 
@@ -200,7 +201,7 @@ func TestAPILFSBatch(t *testing.T) {
 		})
 
 		t.Run("Success", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := newRequest(t, &lfs.BatchRequest{
 				Operation: "download",
@@ -221,10 +222,10 @@ func TestAPILFSBatch(t *testing.T) {
 	})
 
 	t.Run("Upload", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		t.Run("FileTooBig", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			oldMaxFileSize := setting.LFS.MaxFileSize
 			setting.LFS.MaxFileSize = 2
@@ -247,7 +248,7 @@ func TestAPILFSBatch(t *testing.T) {
 		})
 
 		t.Run("AddMeta", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			p := lfs.Pointer{Oid: "05eeb4eb5be71f2dd291ca39157d6d9effd7d1ea19cbdc8a99411fe2a8f26a00", Size: 6}
 
@@ -285,7 +286,7 @@ func TestAPILFSBatch(t *testing.T) {
 		})
 
 		t.Run("AlreadyExists", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := newRequest(t, &lfs.BatchRequest{
 				Operation: "upload",
@@ -302,7 +303,7 @@ func TestAPILFSBatch(t *testing.T) {
 		})
 
 		t.Run("NewFile", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 
 			req := newRequest(t, &lfs.BatchRequest{
 				Operation: "upload",
@@ -328,7 +329,7 @@ func TestAPILFSBatch(t *testing.T) {
 }
 
 func TestAPILFSUpload(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	setting.LFS.StartServer = true
 
@@ -346,7 +347,7 @@ func TestAPILFSUpload(t *testing.T) {
 	}
 
 	t.Run("InvalidPointer", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, lfs.Pointer{Oid: "dummy"}, "")
 
@@ -354,7 +355,7 @@ func TestAPILFSUpload(t *testing.T) {
 	})
 
 	t.Run("AlreadyExistsInStore", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		p := lfs.Pointer{Oid: "83de2e488b89a0aa1c97496b888120a28b0c1e15463a4adb8405578c540f36d4", Size: 6}
 
@@ -389,7 +390,7 @@ func TestAPILFSUpload(t *testing.T) {
 	})
 
 	t.Run("MetaAlreadyExists", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, lfs.Pointer{Oid: oid, Size: 6}, "")
 
@@ -397,7 +398,7 @@ func TestAPILFSUpload(t *testing.T) {
 	})
 
 	t.Run("HashMismatch", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, lfs.Pointer{Oid: "2581dd7bbc1fe44726de4b7dd806a087a978b9c5aec0a60481259e34be09b06a", Size: 1}, "a")
 
@@ -405,7 +406,7 @@ func TestAPILFSUpload(t *testing.T) {
 	})
 
 	t.Run("SizeMismatch", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, lfs.Pointer{Oid: "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", Size: 2}, "a")
 
@@ -413,7 +414,7 @@ func TestAPILFSUpload(t *testing.T) {
 	})
 
 	t.Run("Success", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		p := lfs.Pointer{Oid: "6ccce4863b70f258d691f59609d31b4502e1ba5199942d3bc5d35d17a4ce771d", Size: 5}
 
@@ -433,7 +434,7 @@ func TestAPILFSUpload(t *testing.T) {
 }
 
 func TestAPILFSVerify(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	setting.LFS.StartServer = true
 
@@ -453,7 +454,7 @@ func TestAPILFSVerify(t *testing.T) {
 	}
 
 	t.Run("InvalidJsonRequest", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, nil)
 
@@ -461,7 +462,7 @@ func TestAPILFSVerify(t *testing.T) {
 	})
 
 	t.Run("InvalidPointer", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, &lfs.Pointer{})
 
@@ -469,7 +470,7 @@ func TestAPILFSVerify(t *testing.T) {
 	})
 
 	t.Run("PointerNotExisting", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, &lfs.Pointer{Oid: "fb8f7d8435968c4f82a726a92395be4d16f2f63116caf36c8ad35c60831ab042", Size: 6})
 
@@ -477,7 +478,7 @@ func TestAPILFSVerify(t *testing.T) {
 	})
 
 	t.Run("Success", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := newRequest(t, &lfs.Pointer{Oid: oid, Size: 6})
 
diff --git a/integrations/api_repo_raw_test.go b/tests/integration/api_repo_raw_test.go
similarity index 93%
rename from integrations/api_repo_raw_test.go
rename to tests/integration/api_repo_raw_test.go
index 8e8cc750dd..9793e12b42 100644
--- a/integrations/api_repo_raw_test.go
+++ b/tests/integration/api_repo_raw_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -10,12 +10,13 @@ import (
 
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIReposRaw(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	// Login as User2.
 	session := loginUser(t, user.Name)
diff --git a/integrations/api_repo_tags_test.go b/tests/integration/api_repo_tags_test.go
similarity index 97%
rename from integrations/api_repo_tags_test.go
rename to tests/integration/api_repo_tags_test.go
index 4b87093cdf..5d3a209a76 100644
--- a/integrations/api_repo_tags_test.go
+++ b/tests/integration/api_repo_tags_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -13,12 +13,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIRepoTags(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	// Login as User2.
 	session := loginUser(t, user.Name)
diff --git a/integrations/api_repo_teams_test.go b/tests/integration/api_repo_teams_test.go
similarity index 97%
rename from integrations/api_repo_teams_test.go
rename to tests/integration/api_repo_teams_test.go
index 2ec6958286..1e476a89e2 100644
--- a/integrations/api_repo_teams_test.go
+++ b/tests/integration/api_repo_teams_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -15,12 +15,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIRepoTeams(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// publicOrgRepo = user3/repo21
 	publicOrgRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 32})
diff --git a/integrations/api_repo_test.go b/tests/integration/api_repo_test.go
similarity index 98%
rename from integrations/api_repo_test.go
rename to tests/integration/api_repo_test.go
index 5631df323a..483503ccbb 100644
--- a/integrations/api_repo_test.go
+++ b/tests/integration/api_repo_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -20,12 +20,13 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIUserReposNotLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	req := NewRequestf(t, "GET", "/api/v1/users/%s/repos", user.Name)
@@ -43,7 +44,7 @@ func TestAPIUserReposNotLogin(t *testing.T) {
 }
 
 func TestAPISearchRepo(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	const keyword = "test"
 
 	req := NewRequestf(t, "GET", "/api/v1/repos/search?q=%s", keyword)
@@ -247,7 +248,7 @@ func getRepo(t *testing.T, repoID int64) *repo_model.Repository {
 }
 
 func TestAPIViewRepo(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	var repo api.Repository
 
@@ -277,7 +278,7 @@ func TestAPIViewRepo(t *testing.T) {
 }
 
 func TestAPIOrgRepos(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
 	user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
@@ -323,7 +324,7 @@ func TestAPIOrgRepos(t *testing.T) {
 }
 
 func TestAPIGetRepoByIDUnauthorized(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
 	session := loginUser(t, user.Name)
 	token := getTokenForLoggedInUser(t, session)
@@ -346,7 +347,7 @@ func TestAPIRepoMigrate(t *testing.T) {
 		{ctxUserID: 2, userID: 3, cloneURL: "https://10.0.0.1/user/test_repo.git", repoName: "private-ip", expectedStatus: http.StatusUnprocessableEntity},
 	}
 
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	for _, testCase := range testCases {
 		user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
 		session := loginUser(t, user.Name)
@@ -415,7 +416,7 @@ func testAPIRepoMigrateConflict(t *testing.T, u *url.URL) {
 // mirror-sync must fail with "400 (Bad Request)" when an attempt is made to
 // sync a non-mirror repository.
 func TestAPIMirrorSyncNonMirrorRepo(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 	token := getTokenForLoggedInUser(t, session)
@@ -446,7 +447,7 @@ func TestAPIOrgRepoCreate(t *testing.T) {
 		{ctxUserID: 28, orgName: "user6", repoName: "repo-not-creator", expectedStatus: http.StatusForbidden},
 	}
 
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	for _, testCase := range testCases {
 		user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
 		session := loginUser(t, user.Name)
@@ -512,7 +513,7 @@ func TestAPIRepoTransfer(t *testing.T) {
 		{ctxUserID: 2, newOwner: "user6", teams: nil, expectedStatus: http.StatusCreated},
 	}
 
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// create repo to move
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
@@ -576,7 +577,7 @@ func transfer(t *testing.T) *repo_model.Repository {
 }
 
 func TestAPIAcceptTransfer(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := transfer(t)
 
@@ -602,7 +603,7 @@ func TestAPIAcceptTransfer(t *testing.T) {
 }
 
 func TestAPIRejectTransfer(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := transfer(t)
 
@@ -628,7 +629,7 @@ func TestAPIRejectTransfer(t *testing.T) {
 }
 
 func TestAPIGenerateRepo(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
 	session := loginUser(t, user.Name)
@@ -665,7 +666,7 @@ func TestAPIGenerateRepo(t *testing.T) {
 }
 
 func TestAPIRepoGetReviewers(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	session := loginUser(t, user.Name)
 	token := getTokenForLoggedInUser(t, session)
@@ -679,7 +680,7 @@ func TestAPIRepoGetReviewers(t *testing.T) {
 }
 
 func TestAPIRepoGetAssignees(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	session := loginUser(t, user.Name)
 	token := getTokenForLoggedInUser(t, session)
diff --git a/integrations/api_repo_topic_test.go b/tests/integration/api_repo_topic_test.go
similarity index 98%
rename from integrations/api_repo_topic_test.go
rename to tests/integration/api_repo_topic_test.go
index e99c682e21..4e1e293890 100644
--- a/integrations/api_repo_topic_test.go
+++ b/tests/integration/api_repo_topic_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -14,12 +14,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPITopicSearch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	searchURL, _ := url.Parse("/api/v1/topics/search")
 	var topics struct {
 		TopicNames []*api.TopicResponse `json:"topics"`
@@ -51,7 +52,7 @@ func TestAPITopicSearch(t *testing.T) {
 }
 
 func TestAPIRepoTopic(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of repo2
 	user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) // owner of repo3
 	user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) // write access to repo 3
diff --git a/integrations/api_settings_test.go b/tests/integration/api_settings_test.go
similarity index 96%
rename from integrations/api_settings_test.go
rename to tests/integration/api_settings_test.go
index 10318cec7f..b8da17b963 100644
--- a/integrations/api_settings_test.go
+++ b/tests/integration/api_settings_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -10,12 +10,13 @@ import (
 
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIExposedSettings(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	ui := new(api.GeneralUISettings)
 	req := NewRequest(t, "GET", "/api/v1/settings/ui")
diff --git a/integrations/api_team_test.go b/tests/integration/api_team_test.go
similarity index 98%
rename from integrations/api_team_test.go
rename to tests/integration/api_team_test.go
index 9ea7a6f787..a667949c09 100644
--- a/integrations/api_team_test.go
+++ b/tests/integration/api_team_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -17,12 +17,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/convert"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPITeam(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	teamUser := unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{})
 	team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamUser.TeamID})
@@ -220,7 +221,7 @@ type TeamSearchResults struct {
 }
 
 func TestAPITeamSearch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 17})
@@ -244,7 +245,7 @@ func TestAPITeamSearch(t *testing.T) {
 }
 
 func TestAPIGetTeamRepo(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15})
 	teamRepo := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 24})
diff --git a/integrations/api_team_user_test.go b/tests/integration/api_team_user_test.go
similarity index 94%
rename from integrations/api_team_user_test.go
rename to tests/integration/api_team_user_test.go
index 9b3364b5b1..b999b97a2b 100644
--- a/integrations/api_team_user_test.go
+++ b/tests/integration/api_team_user_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -13,12 +13,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/convert"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPITeamUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	normalUsername := "user2"
 	session := loginUser(t, normalUsername)
diff --git a/integrations/api_token_test.go b/tests/integration/api_token_test.go
similarity index 94%
rename from integrations/api_token_test.go
rename to tests/integration/api_token_test.go
index 6ba4c26a79..023bf30179 100644
--- a/integrations/api_token_test.go
+++ b/tests/integration/api_token_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -12,11 +12,12 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 )
 
 // TestAPICreateAndDeleteToken tests that token that was just created can be deleted
 func TestAPICreateAndDeleteToken(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
 
 	req := NewRequestWithJSON(t, "POST", "/api/v1/users/user1/tokens", map[string]string{
@@ -56,7 +57,7 @@ func TestAPICreateAndDeleteToken(t *testing.T) {
 
 // TestAPIDeleteMissingToken ensures that error is thrown when token not found
 func TestAPIDeleteMissingToken(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
 
 	req := NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%d", unittest.NonexistentID)
diff --git a/integrations/api_user_email_test.go b/tests/integration/api_user_email_test.go
similarity index 94%
rename from integrations/api_user_email_test.go
rename to tests/integration/api_user_email_test.go
index 08d236df30..7bd265187c 100644
--- a/integrations/api_user_email_test.go
+++ b/tests/integration/api_user_email_test.go
@@ -2,19 +2,20 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
 	"testing"
 
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIListEmails(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	normalUsername := "user2"
 	session := loginUser(t, normalUsername)
@@ -41,7 +42,7 @@ func TestAPIListEmails(t *testing.T) {
 }
 
 func TestAPIAddEmail(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	normalUsername := "user2"
 	session := loginUser(t, normalUsername)
@@ -78,7 +79,7 @@ func TestAPIAddEmail(t *testing.T) {
 }
 
 func TestAPIDeleteEmail(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	normalUsername := "user2"
 	session := loginUser(t, normalUsername)
diff --git a/integrations/api_user_heatmap_test.go b/tests/integration/api_user_heatmap_test.go
similarity index 92%
rename from integrations/api_user_heatmap_test.go
rename to tests/integration/api_user_heatmap_test.go
index 6930507645..da6af0118d 100644
--- a/integrations/api_user_heatmap_test.go
+++ b/tests/integration/api_user_heatmap_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.package models
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -12,12 +12,13 @@ import (
 
 	activities_model "code.gitea.io/gitea/models/activities"
 	"code.gitea.io/gitea/modules/timeutil"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestUserHeatmap(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	adminUsername := "user1"
 	normalUsername := "user2"
 	token := getUserToken(t, adminUsername)
diff --git a/integrations/api_user_org_perm_test.go b/tests/integration/api_user_org_perm_test.go
similarity index 95%
rename from integrations/api_user_org_perm_test.go
rename to tests/integration/api_user_org_perm_test.go
index f4047e72be..fef653545c 100644
--- a/integrations/api_user_org_perm_test.go
+++ b/tests/integration/api_user_org_perm_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -10,6 +10,7 @@ import (
 	"testing"
 
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -22,7 +23,7 @@ type apiUserOrgPermTestCase struct {
 }
 
 func TestTokenNeeded(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := emptyTestSession(t)
 	req := NewRequest(t, "GET", "/api/v1/users/user1/orgs/user6/permissions")
@@ -30,7 +31,7 @@ func TestTokenNeeded(t *testing.T) {
 }
 
 func sampleTest(t *testing.T, auoptc apiUserOrgPermTestCase) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, auoptc.LoginUser)
 	token := getTokenForLoggedInUser(t, session)
@@ -123,7 +124,7 @@ func TestCanReadUser(t *testing.T) {
 }
 
 func TestUnknowUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user1")
 	token := getTokenForLoggedInUser(t, session)
@@ -137,7 +138,7 @@ func TestUnknowUser(t *testing.T) {
 }
 
 func TestUnknowOrganization(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user1")
 	token := getTokenForLoggedInUser(t, session)
diff --git a/integrations/api_user_orgs_test.go b/tests/integration/api_user_orgs_test.go
similarity index 96%
rename from integrations/api_user_orgs_test.go
rename to tests/integration/api_user_orgs_test.go
index 1555b53390..622dfdcf21 100644
--- a/integrations/api_user_orgs_test.go
+++ b/tests/integration/api_user_orgs_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.package models
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -12,12 +12,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestUserOrgs(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	adminUsername := "user1"
 	normalUsername := "user2"
 	privateMemberUsername := "user4"
@@ -79,7 +80,7 @@ func getUserOrgs(t *testing.T, userDoer, userCheck string) (orgs []*api.Organiza
 }
 
 func TestMyOrgs(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := emptyTestSession(t)
 	req := NewRequest(t, "GET", "/api/v1/user/orgs")
diff --git a/integrations/api_user_search_test.go b/tests/integration/api_user_search_test.go
similarity index 93%
rename from integrations/api_user_search_test.go
rename to tests/integration/api_user_search_test.go
index dbaca24981..9e9276077b 100644
--- a/integrations/api_user_search_test.go
+++ b/tests/integration/api_user_search_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.package models
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -13,6 +13,7 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -23,7 +24,7 @@ type SearchResults struct {
 }
 
 func TestAPIUserSearchLoggedIn(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	adminUsername := "user1"
 	session := loginUser(t, adminUsername)
 	token := getTokenForLoggedInUser(t, session)
@@ -41,7 +42,7 @@ func TestAPIUserSearchLoggedIn(t *testing.T) {
 }
 
 func TestAPIUserSearchNotLoggedIn(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	query := "user2"
 	req := NewRequestf(t, "GET", "/api/v1/users/search?q=%s", query)
 	resp := MakeRequest(t, req, http.StatusOK)
@@ -62,7 +63,7 @@ func TestAPIUserSearchNotLoggedIn(t *testing.T) {
 }
 
 func TestAPIUserSearchAdminLoggedInUserHidden(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	adminUsername := "user1"
 	session := loginUser(t, adminUsername)
 	token := getTokenForLoggedInUser(t, session)
@@ -82,7 +83,7 @@ func TestAPIUserSearchAdminLoggedInUserHidden(t *testing.T) {
 }
 
 func TestAPIUserSearchNotLoggedInUserHidden(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	query := "user31"
 	req := NewRequestf(t, "GET", "/api/v1/users/search?q=%s", query)
 	resp := MakeRequest(t, req, http.StatusOK)
diff --git a/integrations/api_wiki_test.go b/tests/integration/api_wiki_test.go
similarity index 96%
rename from integrations/api_wiki_test.go
rename to tests/integration/api_wiki_test.go
index 3b768b94d8..c6f4841d08 100644
--- a/integrations/api_wiki_test.go
+++ b/tests/integration/api_wiki_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"encoding/base64"
@@ -11,12 +11,13 @@ import (
 	"testing"
 
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIGetWikiPage(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	username := "user2"
 	session := loginUser(t, username)
@@ -62,7 +63,7 @@ func TestAPIGetWikiPage(t *testing.T) {
 }
 
 func TestAPIListWikiPages(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	username := "user2"
 	session := loginUser(t, username)
@@ -178,7 +179,7 @@ func TestAPINewWikiPage(t *testing.T) {
 		"New page",
 		"&&&&",
 	} {
-		defer prepareTestEnv(t)()
+		defer tests.PrepareTestEnv(t)()
 		username := "user2"
 		session := loginUser(t, username)
 		token := getTokenForLoggedInUser(t, session)
@@ -195,7 +196,7 @@ func TestAPINewWikiPage(t *testing.T) {
 }
 
 func TestAPIEditWikiPage(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	username := "user2"
 	session := loginUser(t, username)
 	token := getTokenForLoggedInUser(t, session)
@@ -211,7 +212,7 @@ func TestAPIEditWikiPage(t *testing.T) {
 }
 
 func TestAPIListPageRevisions(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	username := "user2"
 	session := loginUser(t, username)
 
diff --git a/integrations/attachment_test.go b/tests/integration/attachment_test.go
similarity index 96%
rename from integrations/attachment_test.go
rename to tests/integration/attachment_test.go
index 00e5b9de54..2d2c979f7b 100644
--- a/integrations/attachment_test.go
+++ b/tests/integration/attachment_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
@@ -17,6 +17,7 @@ import (
 	repo_model "code.gitea.io/gitea/models/repo"
 	"code.gitea.io/gitea/modules/storage"
 	"code.gitea.io/gitea/modules/test"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -57,13 +58,13 @@ func createAttachment(t *testing.T, session *TestSession, repoURL, filename stri
 }
 
 func TestCreateAnonymousAttachment(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := emptyTestSession(t)
 	createAttachment(t, session, "user2/repo1", "image.png", generateImg(), http.StatusSeeOther)
 }
 
 func TestCreateIssueAttachment(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	const repoURL = "user2/repo1"
 	session := loginUser(t, "user2")
 	uuid := createAttachment(t, session, repoURL, "image.png", generateImg(), http.StatusOK)
@@ -92,7 +93,7 @@ func TestCreateIssueAttachment(t *testing.T) {
 }
 
 func TestGetAttachment(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	adminSession := loginUser(t, "user1")
 	user2Session := loginUser(t, "user2")
 	user8Session := loginUser(t, "user8")
diff --git a/integrations/auth_ldap_test.go b/tests/integration/auth_ldap_test.go
similarity index 97%
rename from integrations/auth_ldap_test.go
rename to tests/integration/auth_ldap_test.go
index 892ff38134..f3c3e6d7b3 100644
--- a/integrations/auth_ldap_test.go
+++ b/tests/integration/auth_ldap_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"context"
@@ -18,6 +18,7 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/translation"
 	"code.gitea.io/gitea/services/auth"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -145,7 +146,7 @@ func TestLDAPUserSignin(t *testing.T) {
 		t.Skip()
 		return
 	}
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	addAuthSourceLDAP(t, "")
 
 	u := gitLDAPUsers[0]
@@ -162,7 +163,7 @@ func TestLDAPUserSignin(t *testing.T) {
 }
 
 func TestLDAPAuthChange(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	addAuthSourceLDAP(t, "")
 
 	session := loginUser(t, "user1")
@@ -220,7 +221,7 @@ func TestLDAPUserSync(t *testing.T) {
 		t.Skip()
 		return
 	}
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	addAuthSourceLDAP(t, "")
 	auth.SyncExternalUsers(context.Background(), true)
 
@@ -271,7 +272,7 @@ func TestLDAPUserSigninFailed(t *testing.T) {
 		t.Skip()
 		return
 	}
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	addAuthSourceLDAP(t, "")
 
 	u := otherLDAPUsers[0]
@@ -283,7 +284,7 @@ func TestLDAPUserSSHKeySync(t *testing.T) {
 		t.Skip()
 		return
 	}
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	addAuthSourceLDAP(t, "sshPublicKey")
 
 	auth.SyncExternalUsers(context.Background(), true)
@@ -316,7 +317,7 @@ func TestLDAPGroupTeamSyncAddMember(t *testing.T) {
 		t.Skip()
 		return
 	}
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	addAuthSourceLDAP(t, "", "on", `{"cn=ship_crew,ou=people,dc=planetexpress,dc=com":{"org26": ["team11"]},"cn=admin_staff,ou=people,dc=planetexpress,dc=com": {"non-existent": ["non-existent"]}}`)
 	org, err := organization.GetOrgByName("org26")
 	assert.NoError(t, err)
@@ -361,7 +362,7 @@ func TestLDAPGroupTeamSyncRemoveMember(t *testing.T) {
 		t.Skip()
 		return
 	}
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	addAuthSourceLDAP(t, "", "on", `{"cn=dispatch,ou=people,dc=planetexpress,dc=com": {"org26": ["team11"]}}`)
 	org, err := organization.GetOrgByName("org26")
 	assert.NoError(t, err)
@@ -397,7 +398,7 @@ func TestBrokenLDAPMapUserSignin(t *testing.T) {
 		t.Skip()
 		return
 	}
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	addAuthSourceLDAP(t, "", "on", `{"NOT_A_VALID_JSON"["MISSING_DOUBLE_POINT"]}`)
 
 	u := gitLDAPUsers[0]
diff --git a/integrations/benchmarks_test.go b/tests/integration/benchmarks_test.go
similarity index 99%
rename from integrations/benchmarks_test.go
rename to tests/integration/benchmarks_test.go
index a63c363683..bf66d221fb 100644
--- a/integrations/benchmarks_test.go
+++ b/tests/integration/benchmarks_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"math/rand"
diff --git a/integrations/branches_test.go b/tests/integration/branches_test.go
similarity index 94%
rename from integrations/branches_test.go
rename to tests/integration/branches_test.go
index 8b05e24a04..bd0bd63c50 100644
--- a/integrations/branches_test.go
+++ b/tests/integration/branches_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -10,12 +10,13 @@ import (
 	"testing"
 
 	"code.gitea.io/gitea/modules/translation"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestViewBranches(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequest(t, "GET", "/user2/repo1/branches")
 	resp := MakeRequest(t, req, http.StatusOK)
@@ -26,7 +27,7 @@ func TestViewBranches(t *testing.T) {
 }
 
 func TestDeleteBranch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	deleteBranch(t)
 }
diff --git a/integrations/change_default_branch_test.go b/tests/integration/change_default_branch_test.go
similarity index 93%
rename from integrations/change_default_branch_test.go
rename to tests/integration/change_default_branch_test.go
index 6fe7305d45..8edc0e63c4 100644
--- a/integrations/change_default_branch_test.go
+++ b/tests/integration/change_default_branch_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -12,10 +12,11 @@ import (
 	repo_model "code.gitea.io/gitea/models/repo"
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 )
 
 func TestChangeDefaultBranch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
 
diff --git a/integrations/cmd_keys_test.go b/tests/integration/cmd_keys_test.go
similarity index 99%
rename from integrations/cmd_keys_test.go
rename to tests/integration/cmd_keys_test.go
index 3d4194c331..0c72956c29 100644
--- a/integrations/cmd_keys_test.go
+++ b/tests/integration/cmd_keys_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
diff --git a/integrations/compare_test.go b/tests/integration/compare_test.go
similarity index 91%
rename from integrations/compare_test.go
rename to tests/integration/compare_test.go
index 0fb2ae6c91..7642109dd9 100644
--- a/integrations/compare_test.go
+++ b/tests/integration/compare_test.go
@@ -2,18 +2,19 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
 	"strings"
 	"testing"
 
+	"code.gitea.io/gitea/tests"
 	"github.com/stretchr/testify/assert"
 )
 
 func TestCompareTag(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 	req := NewRequest(t, "GET", "/user2/repo1/compare/v1.1...master")
@@ -30,7 +31,7 @@ func TestCompareTag(t *testing.T) {
 
 // Compare with inferred default branch (master)
 func TestCompareDefault(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 	req := NewRequest(t, "GET", "/user2/repo1/compare/v1.1")
diff --git a/integrations/cors_test.go b/tests/integration/cors_test.go
similarity index 88%
rename from integrations/cors_test.go
rename to tests/integration/cors_test.go
index 466984c79a..f531801627 100644
--- a/integrations/cors_test.go
+++ b/tests/integration/cors_test.go
@@ -2,17 +2,18 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
 	"testing"
 
+	"code.gitea.io/gitea/tests"
 	"github.com/stretchr/testify/assert"
 )
 
 func TestCORSNotSet(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequestf(t, "GET", "/api/v1/version")
 	session := loginUser(t, "user2")
 	resp := session.MakeRequest(t, req, http.StatusOK)
diff --git a/integrations/create_no_session_test.go b/tests/integration/create_no_session_test.go
similarity index 95%
rename from integrations/create_no_session_test.go
rename to tests/integration/create_no_session_test.go
index 017fe1d356..c9b90974d7 100644
--- a/integrations/create_no_session_test.go
+++ b/tests/integration/create_no_session_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"context"
@@ -16,6 +16,7 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/routers"
+	"code.gitea.io/gitea/tests"
 
 	"gitea.com/go-chi/session"
 	"github.com/stretchr/testify/assert"
@@ -53,7 +54,7 @@ func sessionFileExist(t *testing.T, tmpDir, sessionID string) bool {
 }
 
 func TestSessionFileCreation(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	oldSessionConfig := setting.SessionConfig.ProviderConfig
 	defer func() {
@@ -86,7 +87,7 @@ func TestSessionFileCreation(t *testing.T) {
 	c = routers.NormalRoutes(context.TODO())
 
 	t.Run("NoSessionOnViewIssue", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", "/user2/repo1/issues/1")
 		resp := MakeRequest(t, req, http.StatusOK)
@@ -96,7 +97,7 @@ func TestSessionFileCreation(t *testing.T) {
 		assert.False(t, sessionFileExist(t, tmpDir, sessionID))
 	})
 	t.Run("CreateSessionOnLogin", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		req := NewRequest(t, "GET", "/user/login")
 		resp := MakeRequest(t, req, http.StatusOK)
diff --git a/integrations/csrf_test.go b/tests/integration/csrf_test.go
similarity index 95%
rename from integrations/csrf_test.go
rename to tests/integration/csrf_test.go
index 2c61f95426..18a157412b 100644
--- a/integrations/csrf_test.go
+++ b/tests/integration/csrf_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -12,12 +12,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestCsrfProtection(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// test web form csrf via form
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
diff --git a/integrations/delete_user_test.go b/tests/integration/delete_user_test.go
similarity index 94%
rename from integrations/delete_user_test.go
rename to tests/integration/delete_user_test.go
index 8b86780224..1d9d257f12 100644
--- a/integrations/delete_user_test.go
+++ b/tests/integration/delete_user_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -15,6 +15,7 @@ import (
 	repo_model "code.gitea.io/gitea/models/repo"
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 )
 
 func assertUserDeleted(t *testing.T, userID int64) {
@@ -30,7 +31,7 @@ func assertUserDeleted(t *testing.T, userID int64) {
 }
 
 func TestUserDeleteAccount(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user8")
 	csrf := GetCSRF(t, session, "/user/settings/account")
@@ -45,7 +46,7 @@ func TestUserDeleteAccount(t *testing.T) {
 }
 
 func TestUserDeleteAccountStillOwnRepos(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 	csrf := GetCSRF(t, session, "/user/settings/account")
diff --git a/integrations/download_test.go b/tests/integration/download_test.go
similarity index 91%
rename from integrations/download_test.go
rename to tests/integration/download_test.go
index f46122d951..9d3b17d103 100644
--- a/integrations/download_test.go
+++ b/tests/integration/download_test.go
@@ -2,19 +2,20 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
 	"testing"
 
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestDownloadByID(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
@@ -26,7 +27,7 @@ func TestDownloadByID(t *testing.T) {
 }
 
 func TestDownloadByIDForSVGUsesSecureHeaders(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
@@ -40,7 +41,7 @@ func TestDownloadByIDForSVGUsesSecureHeaders(t *testing.T) {
 }
 
 func TestDownloadByIDMedia(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
@@ -52,7 +53,7 @@ func TestDownloadByIDMedia(t *testing.T) {
 }
 
 func TestDownloadByIDMediaForSVGUsesSecureHeaders(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
@@ -66,7 +67,7 @@ func TestDownloadByIDMediaForSVGUsesSecureHeaders(t *testing.T) {
 }
 
 func TestDownloadRawTextFileWithoutMimeTypeMapping(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
@@ -77,7 +78,7 @@ func TestDownloadRawTextFileWithoutMimeTypeMapping(t *testing.T) {
 }
 
 func TestDownloadRawTextFileWithMimeTypeMapping(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	setting.MimeTypeMap.Map[".xml"] = "text/xml"
 	setting.MimeTypeMap.Enabled = true
 
diff --git a/integrations/dump_restore_test.go b/tests/integration/dump_restore_test.go
similarity index 99%
rename from integrations/dump_restore_test.go
rename to tests/integration/dump_restore_test.go
index 7395bd5bd9..19513d0271 100644
--- a/integrations/dump_restore_test.go
+++ b/tests/integration/dump_restore_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"context"
diff --git a/integrations/editor_test.go b/tests/integration/editor_test.go
similarity index 99%
rename from integrations/editor_test.go
rename to tests/integration/editor_test.go
index c6c5ab2f61..19e80dc7bf 100644
--- a/integrations/editor_test.go
+++ b/tests/integration/editor_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
diff --git a/integrations/empty_repo_test.go b/tests/integration/empty_repo_test.go
similarity index 91%
rename from integrations/empty_repo_test.go
rename to tests/integration/empty_repo_test.go
index daf153a183..8810363dc8 100644
--- a/integrations/empty_repo_test.go
+++ b/tests/integration/empty_repo_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -11,10 +11,11 @@ import (
 	repo_model "code.gitea.io/gitea/models/repo"
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 )
 
 func TestEmptyRepo(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	subpaths := []string{
 		"commits/master",
 		"raw/foo",
diff --git a/integrations/eventsource_test.go b/tests/integration/eventsource_test.go
similarity index 96%
rename from integrations/eventsource_test.go
rename to tests/integration/eventsource_test.go
index 4bb607cde4..cd496e0129 100644
--- a/integrations/eventsource_test.go
+++ b/tests/integration/eventsource_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -16,12 +16,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/eventsource"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestEventSourceManagerRun(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	manager := eventsource.GetManager()
 
 	eventChan := manager.Register(2)
diff --git a/integrations/explore_repos_test.go b/tests/integration/explore_repos_test.go
similarity index 79%
rename from integrations/explore_repos_test.go
rename to tests/integration/explore_repos_test.go
index c6f695612a..dca3252753 100644
--- a/integrations/explore_repos_test.go
+++ b/tests/integration/explore_repos_test.go
@@ -2,15 +2,17 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
 	"testing"
+
+	"code.gitea.io/gitea/tests"
 )
 
 func TestExploreRepos(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequest(t, "GET", "/explore/repos")
 	MakeRequest(t, req, http.StatusOK)
diff --git a/integrations/git_clone_wiki_test.go b/tests/integration/git_clone_wiki_test.go
similarity index 94%
rename from integrations/git_clone_wiki_test.go
rename to tests/integration/git_clone_wiki_test.go
index a73174f6aa..4bdbc9b7c3 100644
--- a/integrations/git_clone_wiki_test.go
+++ b/tests/integration/git_clone_wiki_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"context"
@@ -14,6 +14,7 @@ import (
 
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -32,7 +33,7 @@ func assertFileEqual(t *testing.T, p string, content []byte) {
 
 func TestRepoCloneWiki(t *testing.T) {
 	onGiteaRun(t, func(t *testing.T, u *url.URL) {
-		defer prepareTestEnv(t)()
+		defer tests.PrepareTestEnv(t)()
 
 		dstPath, err := os.MkdirTemp("", "clone_wiki")
 		assert.NoError(t, err)
diff --git a/integrations/git_helper_for_declarative_test.go b/tests/integration/git_helper_for_declarative_test.go
similarity index 98%
rename from integrations/git_helper_for_declarative_test.go
rename to tests/integration/git_helper_for_declarative_test.go
index 1ea594b739..666f9f6fe9 100644
--- a/integrations/git_helper_for_declarative_test.go
+++ b/tests/integration/git_helper_for_declarative_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"context"
@@ -21,6 +21,7 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/ssh"
 	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -61,7 +62,7 @@ func createSSHUrl(gitPath string, u *url.URL) *url.URL {
 
 func onGiteaRunTB(t testing.TB, callback func(testing.TB, *url.URL), prepare ...bool) {
 	if len(prepare) == 0 || prepare[0] {
-		defer prepareTestEnv(t, 1)()
+		defer tests.PrepareTestEnv(t, 1)()
 	}
 	s := http.Server{
 		Handler: c,
diff --git a/integrations/git_smart_http_test.go b/tests/integration/git_smart_http_test.go
similarity index 98%
rename from integrations/git_smart_http_test.go
rename to tests/integration/git_smart_http_test.go
index a6baafe374..02b0e93870 100644
--- a/integrations/git_smart_http_test.go
+++ b/tests/integration/git_smart_http_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"io"
diff --git a/integrations/git_test.go b/tests/integration/git_test.go
similarity index 97%
rename from integrations/git_test.go
rename to tests/integration/git_test.go
index 9018374514..caeb5db8b3 100644
--- a/integrations/git_test.go
+++ b/tests/integration/git_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"encoding/hex"
@@ -28,6 +28,7 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -50,7 +51,7 @@ func testGit(t *testing.T, u *url.URL) {
 	forkedUserCtx := NewAPITestContext(t, "user4", "repo1")
 
 	t.Run("HTTP", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 		ensureAnonymousClone(t, u)
 		httpContext := baseAPITestContext
 		httpContext.Reponame = "repo-tmp-17"
@@ -86,7 +87,7 @@ func testGit(t *testing.T, u *url.URL) {
 		t.Run("AutoMerge", doAutoPRMerge(&httpContext, dstPath))
 		t.Run("CreatePRAndSetManuallyMerged", doCreatePRAndSetManuallyMerged(httpContext, httpContext, dstPath, "master", "test-manually-merge"))
 		t.Run("MergeFork", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			t.Run("CreatePRAndMerge", doMergeFork(httpContext, forkedUserCtx, "master", httpContext.Username+":master"))
 			rawTest(t, &forkedUserCtx, little, big, littleLFS, bigLFS)
 			mediaTest(t, &forkedUserCtx, little, big, littleLFS, bigLFS)
@@ -95,7 +96,7 @@ func testGit(t *testing.T, u *url.URL) {
 		t.Run("PushCreate", doPushCreate(httpContext, u))
 	})
 	t.Run("SSH", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 		sshContext := baseAPITestContext
 		sshContext.Reponame = "repo-tmp-18"
 		keyname := "my-testing-key"
@@ -127,7 +128,7 @@ func testGit(t *testing.T, u *url.URL) {
 			t.Run("CreateAgitFlowPull", doCreateAgitFlowPull(dstPath, &sshContext, "master", "test/head2"))
 			t.Run("BranchProtectMerge", doBranchProtectPRMerge(&sshContext, dstPath))
 			t.Run("MergeFork", func(t *testing.T) {
-				defer PrintCurrentTest(t)()
+				defer tests.PrintCurrentTest(t)()
 				t.Run("CreatePRAndMerge", doMergeFork(sshContext, forkedUserCtx, "master", sshContext.Username+":master"))
 				rawTest(t, &forkedUserCtx, little, big, littleLFS, bigLFS)
 				mediaTest(t, &forkedUserCtx, little, big, littleLFS, bigLFS)
@@ -147,7 +148,7 @@ func ensureAnonymousClone(t *testing.T, u *url.URL) {
 
 func standardCommitAndPushTest(t *testing.T, dstPath string) (little, big string) {
 	t.Run("Standard", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 		little, big = commitAndPushTest(t, dstPath, "data-file-")
 	})
 	return little, big
@@ -155,7 +156,7 @@ func standardCommitAndPushTest(t *testing.T, dstPath string) (little, big string
 
 func lfsCommitAndPushTest(t *testing.T, dstPath string) (littleLFS, bigLFS string) {
 	t.Run("LFS", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 		prefix := "lfs-data-file-"
 		err := git.NewCommand(git.DefaultContext, "lfs").AddArguments("install").Run(&git.RunOpts{Dir: dstPath})
 		assert.NoError(t, err)
@@ -182,7 +183,7 @@ func lfsCommitAndPushTest(t *testing.T, dstPath string) (littleLFS, bigLFS strin
 		littleLFS, bigLFS = commitAndPushTest(t, dstPath, prefix)
 
 		t.Run("Locks", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			lockTest(t, dstPath)
 		})
 	})
@@ -191,9 +192,9 @@ func lfsCommitAndPushTest(t *testing.T, dstPath string) (littleLFS, bigLFS strin
 
 func commitAndPushTest(t *testing.T, dstPath, prefix string) (little, big string) {
 	t.Run("PushCommit", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 		t.Run("Little", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			little = doCommitAndPush(t, littleSize, dstPath, prefix)
 		})
 		t.Run("Big", func(t *testing.T) {
@@ -201,7 +202,7 @@ func commitAndPushTest(t *testing.T, dstPath, prefix string) (little, big string
 				t.Skip("Skipping test in short mode.")
 				return
 			}
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			big = doCommitAndPush(t, bigSize, dstPath, prefix)
 		})
 	})
@@ -210,7 +211,7 @@ func commitAndPushTest(t *testing.T, dstPath, prefix string) (little, big string
 
 func rawTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS string) {
 	t.Run("Raw", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 		username := ctx.Username
 		reponame := ctx.Reponame
 
@@ -250,7 +251,7 @@ func rawTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS s
 
 func mediaTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS string) {
 	t.Run("Media", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		username := ctx.Username
 		reponame := ctx.Reponame
@@ -362,7 +363,7 @@ func generateCommitWithNewData(size int, repoPath, email, fullName, prefix strin
 
 func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
 	return func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 		t.Run("CreateBranchProtected", doGitCreateBranch(dstPath, "protected"))
 		t.Run("PushProtectedBranch", doGitPushTestRepository(dstPath, "origin", "protected"))
 
@@ -452,7 +453,7 @@ func doProtectBranch(ctx APITestContext, branch, userToWhitelist, unprotectedFil
 
 func doMergeFork(ctx, baseCtx APITestContext, baseBranch, headBranch string) func(t *testing.T) {
 	return func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 		var pr api.PullRequest
 		var err error
 
@@ -500,7 +501,7 @@ func doMergeFork(ctx, baseCtx APITestContext, baseBranch, headBranch string) fun
 
 func doCreatePRAndSetManuallyMerged(ctx, baseCtx APITestContext, dstPath, baseBranch, headBranch string) func(t *testing.T) {
 	return func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 		var (
 			pr           api.PullRequest
 			err          error
@@ -552,7 +553,7 @@ func doEnsureDiffNoChange(ctx APITestContext, pr api.PullRequest, diffHash strin
 
 func doPushCreate(ctx APITestContext, u *url.URL) func(t *testing.T) {
 	return func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		// create a context for a currently non-existent repository
 		ctx.Reponame = fmt.Sprintf("repo-tmp-push-create-%s", u.Scheme)
@@ -610,7 +611,7 @@ func doBranchDelete(ctx APITestContext, owner, repo, branch string) func(*testin
 
 func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
 	return func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		ctx := NewAPITestContext(t, baseCtx.Username, baseCtx.Reponame)
 
@@ -692,7 +693,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
 
 func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, baseBranch, headBranch string) func(t *testing.T) {
 	return func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		// skip this test if git version is low
 		if git.CheckGitVersionAtLeast("2.29") != nil {
diff --git a/integrations/goget_test.go b/tests/integration/goget_test.go
similarity index 91%
rename from integrations/goget_test.go
rename to tests/integration/goget_test.go
index 504d869990..c969f4aff1 100644
--- a/integrations/goget_test.go
+++ b/tests/integration/goget_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -10,12 +10,13 @@ import (
 	"testing"
 
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestGoGet(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequest(t, "GET", "/blah/glah/plah?go-get=1")
 	resp := MakeRequest(t, req, http.StatusOK)
diff --git a/integrations/gpg_git_test.go b/tests/integration/gpg_git_test.go
similarity index 94%
rename from integrations/gpg_git_test.go
rename to tests/integration/gpg_git_test.go
index 6edce606f2..2e16d150c8 100644
--- a/integrations/gpg_git_test.go
+++ b/tests/integration/gpg_git_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"encoding/base64"
@@ -17,6 +17,7 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 	"golang.org/x/crypto/openpgp"
@@ -24,7 +25,7 @@ import (
 )
 
 func TestGPGGit(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	username := "user2"
 
 	// OK Set a new GPG home
@@ -71,7 +72,7 @@ func TestGPGGit(t *testing.T) {
 		u.Path = baseAPITestContext.GitPath()
 
 		t.Run("Unsigned-Initial", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-unsigned")
 			t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
 			t.Run("CheckMasterBranchUnsigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
@@ -95,7 +96,7 @@ func TestGPGGit(t *testing.T) {
 		u.Path = baseAPITestContext.GitPath()
 
 		t.Run("Unsigned-Initial-CRUD-ParentSigned", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-unsigned")
 			t.Run("CreateCRUDFile-ParentSigned", crudActionCreateFile(
 				t, testCtx, user, "master", "parentsigned", "signed-parent.txt", func(t *testing.T, response api.FileResponse) {
@@ -112,7 +113,7 @@ func TestGPGGit(t *testing.T) {
 		u.Path = baseAPITestContext.GitPath()
 
 		t.Run("Unsigned-Initial-CRUD-Never", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-unsigned")
 			t.Run("CreateCRUDFile-Never", crudActionCreateFile(
 				t, testCtx, user, "parentsigned", "parentsigned-never", "unsigned-never2.txt", func(t *testing.T, response api.FileResponse) {
@@ -125,7 +126,7 @@ func TestGPGGit(t *testing.T) {
 		u.Path = baseAPITestContext.GitPath()
 
 		t.Run("Unsigned-Initial-CRUD-Always", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-unsigned")
 			t.Run("CreateCRUDFile-Always", crudActionCreateFile(
 				t, testCtx, user, "master", "always", "signed-always.txt", func(t *testing.T, response api.FileResponse) {
@@ -162,7 +163,7 @@ func TestGPGGit(t *testing.T) {
 		u.Path = baseAPITestContext.GitPath()
 
 		t.Run("Unsigned-Initial-CRUD-ParentSigned", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-unsigned")
 			t.Run("CreateCRUDFile-Always-ParentSigned", crudActionCreateFile(
 				t, testCtx, user, "always", "always-parentsigned", "signed-always-parentsigned.txt", func(t *testing.T, response api.FileResponse) {
@@ -185,7 +186,7 @@ func TestGPGGit(t *testing.T) {
 		u.Path = baseAPITestContext.GitPath()
 
 		t.Run("AlwaysSign-Initial", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-always")
 			t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
 			t.Run("CheckMasterBranchSigned", doAPIGetBranch(testCtx, "master", func(t *testing.T, branch api.Branch) {
@@ -213,7 +214,7 @@ func TestGPGGit(t *testing.T) {
 		u.Path = baseAPITestContext.GitPath()
 
 		t.Run("AlwaysSign-Initial-CRUD-Never", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-always-never")
 			t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
 			t.Run("CreateCRUDFile-Never", crudActionCreateFile(
@@ -226,7 +227,7 @@ func TestGPGGit(t *testing.T) {
 	onGiteaRun(t, func(t *testing.T, u *url.URL) {
 		u.Path = baseAPITestContext.GitPath()
 		t.Run("AlwaysSign-Initial-CRUD-ParentSigned-On-Always", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-always-parent")
 			t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
 			t.Run("CreateCRUDFile-ParentSigned", crudActionCreateFile(
@@ -245,7 +246,7 @@ func TestGPGGit(t *testing.T) {
 		u.Path = baseAPITestContext.GitPath()
 
 		t.Run("AlwaysSign-Initial-CRUD-Always", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-always-always")
 			t.Run("CreateRepository", doAPICreateRepository(testCtx, false))
 			t.Run("CreateCRUDFile-Always", crudActionCreateFile(
@@ -265,7 +266,7 @@ func TestGPGGit(t *testing.T) {
 		u.Path = baseAPITestContext.GitPath()
 
 		t.Run("UnsignedMerging", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-unsigned")
 			var err error
 			t.Run("CreatePullRequest", func(t *testing.T) {
@@ -286,7 +287,7 @@ func TestGPGGit(t *testing.T) {
 		u.Path = baseAPITestContext.GitPath()
 
 		t.Run("BaseSignedMerging", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-unsigned")
 			var err error
 			t.Run("CreatePullRequest", func(t *testing.T) {
@@ -307,7 +308,7 @@ func TestGPGGit(t *testing.T) {
 		u.Path = baseAPITestContext.GitPath()
 
 		t.Run("CommitsSignedMerging", func(t *testing.T) {
-			defer PrintCurrentTest(t)()
+			defer tests.PrintCurrentTest(t)()
 			testCtx := NewAPITestContext(t, username, "initial-unsigned")
 			var err error
 			t.Run("CreatePullRequest", func(t *testing.T) {
@@ -344,10 +345,10 @@ func crudActionCreateFile(t *testing.T, ctx APITestContext, user *user_model.Use
 }
 
 func importTestingKey(tmpDir, name, email string) (*openpgp.Entity, error) {
-	if _, _, err := process.GetManager().Exec("gpg --import integrations/private-testing.key", "gpg", "--import", "integrations/private-testing.key"); err != nil {
+	if _, _, err := process.GetManager().Exec("gpg --import tests/integration/private-testing.key", "gpg", "--import", "tests/integration/private-testing.key"); err != nil {
 		return nil, err
 	}
-	keyringFile, err := os.Open("integrations/private-testing.key")
+	keyringFile, err := os.Open("tests/integration/private-testing.key")
 	if err != nil {
 		return nil, err
 	}
diff --git a/integrations/html_helper.go b/tests/integration/html_helper.go
similarity index 98%
rename from integrations/html_helper.go
rename to tests/integration/html_helper.go
index 001fc9a05b..35d61f7b3e 100644
--- a/integrations/html_helper.go
+++ b/tests/integration/html_helper.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
diff --git a/integrations/integration_test.go b/tests/integration/integration_test.go
similarity index 58%
rename from integrations/integration_test.go
rename to tests/integration/integration_test.go
index a506c6a825..8fc8a854a7 100644
--- a/integrations/integration_test.go
+++ b/tests/integration/integration_test.go
@@ -2,12 +2,11 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
 	"context"
-	"database/sql"
 	"fmt"
 	"hash"
 	"hash/fnv"
@@ -17,26 +16,20 @@ import (
 	"net/http/httptest"
 	"net/url"
 	"os"
-	"path"
 	"path/filepath"
-	"runtime"
 	"strings"
 	"testing"
 	"time"
 
 	"code.gitea.io/gitea/models/unittest"
-	"code.gitea.io/gitea/modules/base"
-	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/graceful"
 	"code.gitea.io/gitea/modules/json"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/queue"
-	repo_module "code.gitea.io/gitea/modules/repository"
 	"code.gitea.io/gitea/modules/setting"
-	"code.gitea.io/gitea/modules/storage"
 	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/modules/web"
 	"code.gitea.io/gitea/routers"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/PuerkitoBio/goquery"
 	"github.com/stretchr/testify/assert"
@@ -88,27 +81,27 @@ func TestMain(m *testing.M) {
 	graceful.InitManager(managerCtx)
 	defer cancel()
 
-	initIntegrationTest()
+	tests.InitTest(true)
 	c = routers.NormalRoutes(context.TODO())
 
 	// integration test settings...
 	if setting.Cfg != nil {
 		testingCfg := setting.Cfg.Section("integration-tests")
-		slowTest = testingCfg.Key("SLOW_TEST").MustDuration(slowTest)
-		slowFlush = testingCfg.Key("SLOW_FLUSH").MustDuration(slowFlush)
+		tests.SlowTest = testingCfg.Key("SLOW_TEST").MustDuration(tests.SlowTest)
+		tests.SlowFlush = testingCfg.Key("SLOW_FLUSH").MustDuration(tests.SlowFlush)
 	}
 
 	if os.Getenv("GITEA_SLOW_TEST_TIME") != "" {
 		duration, err := time.ParseDuration(os.Getenv("GITEA_SLOW_TEST_TIME"))
 		if err == nil {
-			slowTest = duration
+			tests.SlowTest = duration
 		}
 	}
 
 	if os.Getenv("GITEA_SLOW_FLUSH_TIME") != "" {
 		duration, err := time.ParseDuration(os.Getenv("GITEA_SLOW_FLUSH_TIME"))
 		if err == nil {
-			slowFlush = duration
+			tests.SlowFlush = duration
 		}
 	}
 
@@ -130,7 +123,7 @@ func TestMain(m *testing.M) {
 	}
 	exitCode := m.Run()
 
-	writerCloser.Reset()
+	tests.WriterCloser.Reset()
 
 	if err = util.RemoveAll(setting.Indexer.IssuePath); err != nil {
 		fmt.Printf("util.RemoveAll: %v\n", err)
@@ -144,169 +137,6 @@ func TestMain(m *testing.M) {
 	os.Exit(exitCode)
 }
 
-func initIntegrationTest() {
-	giteaRoot := base.SetupGiteaRoot()
-	if giteaRoot == "" {
-		fmt.Println("Environment variable $GITEA_ROOT not set")
-		os.Exit(1)
-	}
-	giteaBinary := "gitea"
-	if runtime.GOOS == "windows" {
-		giteaBinary += ".exe"
-	}
-	setting.AppPath = path.Join(giteaRoot, giteaBinary)
-	if _, err := os.Stat(setting.AppPath); err != nil {
-		fmt.Printf("Could not find gitea binary at %s\n", setting.AppPath)
-		os.Exit(1)
-	}
-
-	giteaConf := os.Getenv("GITEA_CONF")
-	if giteaConf == "" {
-		fmt.Println("Environment variable $GITEA_CONF not set")
-		os.Exit(1)
-	} else if !path.IsAbs(giteaConf) {
-		setting.CustomConf = path.Join(giteaRoot, giteaConf)
-	} else {
-		setting.CustomConf = giteaConf
-	}
-
-	setting.SetCustomPathAndConf("", "", "")
-	setting.LoadForTest()
-	setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master"
-	_ = util.RemoveAll(repo_module.LocalCopyPath())
-
-	if err := git.InitFull(context.Background()); err != nil {
-		log.Fatal("git.InitOnceWithSync: %v", err)
-	}
-
-	setting.InitDBConfig()
-	if err := storage.Init(); err != nil {
-		fmt.Printf("Init storage failed: %v", err)
-		os.Exit(1)
-	}
-
-	switch {
-	case setting.Database.UseMySQL:
-		connType := "tcp"
-		if len(setting.Database.Host) > 0 && setting.Database.Host[0] == '/' { // looks like a unix socket
-			connType = "unix"
-		}
-
-		db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@%s(%s)/",
-			setting.Database.User, setting.Database.Passwd, connType, setting.Database.Host))
-		defer db.Close()
-		if err != nil {
-			log.Fatal("sql.Open: %v", err)
-		}
-		if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name)); err != nil {
-			log.Fatal("db.Exec: %v", err)
-		}
-	case setting.Database.UsePostgreSQL:
-		var db *sql.DB
-		var err error
-		if setting.Database.Host[0] == '/' {
-			db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@/%s?sslmode=%s&host=%s",
-				setting.Database.User, setting.Database.Passwd, setting.Database.Name, setting.Database.SSLMode, setting.Database.Host))
-		} else {
-			db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
-				setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
-		}
-
-		defer db.Close()
-		if err != nil {
-			log.Fatal("sql.Open: %v", err)
-		}
-		dbrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", setting.Database.Name))
-		if err != nil {
-			log.Fatal("db.Query: %v", err)
-		}
-		defer dbrows.Close()
-
-		if !dbrows.Next() {
-			if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", setting.Database.Name)); err != nil {
-				log.Fatal("db.Exec: CREATE DATABASE: %v", err)
-			}
-		}
-		// Check if we need to setup a specific schema
-		if len(setting.Database.Schema) == 0 {
-			break
-		}
-		db.Close()
-
-		if setting.Database.Host[0] == '/' {
-			db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@/%s?sslmode=%s&host=%s",
-				setting.Database.User, setting.Database.Passwd, setting.Database.Name, setting.Database.SSLMode, setting.Database.Host))
-		} else {
-			db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
-				setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
-		}
-		// This is a different db object; requires a different Close()
-		defer db.Close()
-		if err != nil {
-			log.Fatal("sql.Open: %v", err)
-		}
-		schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema))
-		if err != nil {
-			log.Fatal("db.Query: %v", err)
-		}
-		defer schrows.Close()
-
-		if !schrows.Next() {
-			// Create and setup a DB schema
-			if _, err = db.Exec(fmt.Sprintf("CREATE SCHEMA %s", setting.Database.Schema)); err != nil {
-				log.Fatal("db.Exec: CREATE SCHEMA: %v", err)
-			}
-		}
-
-	case setting.Database.UseMSSQL:
-		host, port := setting.ParseMSSQLHostPort(setting.Database.Host)
-		db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
-			host, port, "master", setting.Database.User, setting.Database.Passwd))
-		if err != nil {
-			log.Fatal("sql.Open: %v", err)
-		}
-		if _, err := db.Exec(fmt.Sprintf("If(db_id(N'%s') IS NULL) BEGIN CREATE DATABASE %s; END;", setting.Database.Name, setting.Database.Name)); err != nil {
-			log.Fatal("db.Exec: %v", err)
-		}
-		defer db.Close()
-	}
-
-	routers.GlobalInitInstalled(graceful.GetManager().HammerContext())
-}
-
-func prepareTestEnv(t testing.TB, skip ...int) func() {
-	t.Helper()
-	ourSkip := 2
-	if len(skip) > 0 {
-		ourSkip += skip[0]
-	}
-	deferFn := PrintCurrentTest(t, ourSkip)
-	assert.NoError(t, unittest.LoadFixtures())
-	assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
-	assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath))
-	ownerDirs, err := os.ReadDir(setting.RepoRootPath)
-	if err != nil {
-		assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
-	}
-	for _, ownerDir := range ownerDirs {
-		if !ownerDir.Type().IsDir() {
-			continue
-		}
-		repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
-		if err != nil {
-			assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
-		}
-		for _, repoDir := range repoDirs {
-			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0o755)
-			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0o755)
-			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0o755)
-			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0o755)
-		}
-	}
-
-	return deferFn
-}
-
 type TestSession struct {
 	jar http.CookieJar
 }
@@ -575,32 +405,3 @@ func GetCSRF(t testing.TB, session *TestSession, urlStr string) string {
 	doc := NewHTMLParser(t, resp.Body)
 	return doc.GetCSRF()
 }
-
-// resetFixtures flushes queues, reloads fixtures and resets test repositories within a single test.
-// Most tests should call defer prepareTestEnv(t)() (or have onGiteaRun do that for them) but sometimes
-// within a single test this is required
-func resetFixtures(t *testing.T) {
-	assert.NoError(t, queue.GetManager().FlushAll(context.Background(), -1))
-	assert.NoError(t, unittest.LoadFixtures())
-	assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
-	assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath))
-	ownerDirs, err := os.ReadDir(setting.RepoRootPath)
-	if err != nil {
-		assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
-	}
-	for _, ownerDir := range ownerDirs {
-		if !ownerDir.Type().IsDir() {
-			continue
-		}
-		repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
-		if err != nil {
-			assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
-		}
-		for _, repoDir := range repoDirs {
-			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0o755)
-			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0o755)
-			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0o755)
-			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0o755)
-		}
-	}
-}
diff --git a/integrations/issue_test.go b/tests/integration/issue_test.go
similarity index 97%
rename from integrations/issue_test.go
rename to tests/integration/issue_test.go
index 4bbb4744ea..1f0f894ca4 100644
--- a/integrations/issue_test.go
+++ b/tests/integration/issue_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -24,6 +24,7 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/test"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/PuerkitoBio/goquery"
 	"github.com/stretchr/testify/assert"
@@ -57,14 +58,14 @@ func assertMatch(t testing.TB, issue *issues_model.Issue, keyword string) {
 }
 
 func TestNoLoginViewIssues(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequest(t, "GET", "/user2/repo1/issues")
 	MakeRequest(t, req, http.StatusOK)
 }
 
 func TestViewIssuesSortByType(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
@@ -92,7 +93,7 @@ func TestViewIssuesSortByType(t *testing.T) {
 }
 
 func TestViewIssuesKeyword(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{
@@ -117,7 +118,7 @@ func TestViewIssuesKeyword(t *testing.T) {
 }
 
 func TestNoLoginViewIssue(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequest(t, "GET", "/user2/repo1/issues/1")
 	MakeRequest(t, req, http.StatusOK)
@@ -184,13 +185,13 @@ func testIssueAddComment(t *testing.T, session *TestSession, issueURL, content,
 }
 
 func TestNewIssue(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user2")
 	testNewIssue(t, session, "user2", "repo1", "Title", "Description")
 }
 
 func TestIssueCommentClose(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user2")
 	issueURL := testNewIssue(t, session, "user2", "repo1", "Title", "Description")
 	testIssueAddComment(t, session, issueURL, "Test comment 1", "")
@@ -206,7 +207,7 @@ func TestIssueCommentClose(t *testing.T) {
 }
 
 func TestIssueReaction(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user2")
 	issueURL := testNewIssue(t, session, "user2", "repo1", "Title", "Description")
 
@@ -232,7 +233,7 @@ func TestIssueReaction(t *testing.T) {
 }
 
 func TestIssueCrossReference(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// Issue that will be referenced
 	_, issueBase := testIssueWithBean(t, "user2", 1, "Title", "Description")
@@ -332,7 +333,7 @@ func testIssueChangeInfo(t *testing.T, user, issueURL, info, value string) {
 }
 
 func TestIssueRedirect(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user2")
 
 	// Test external tracker where style not set (shall default numeric)
@@ -352,7 +353,7 @@ func TestIssueRedirect(t *testing.T) {
 }
 
 func TestSearchIssues(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
@@ -448,7 +449,7 @@ func TestSearchIssues(t *testing.T) {
 }
 
 func TestSearchIssuesWithLabels(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	expectedIssueCount := 15 // from the fixtures
 	if expectedIssueCount > setting.UI.IssuePagingNum {
@@ -508,7 +509,7 @@ func TestSearchIssuesWithLabels(t *testing.T) {
 }
 
 func TestGetIssueInfo(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 10})
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
@@ -529,7 +530,7 @@ func TestGetIssueInfo(t *testing.T) {
 }
 
 func TestUpdateIssueDeadline(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	issueBefore := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 10})
 	repoBefore := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issueBefore.RepoID})
diff --git a/integrations/lfs_getobject_test.go b/tests/integration/lfs_getobject_test.go
similarity index 95%
rename from integrations/lfs_getobject_test.go
rename to tests/integration/lfs_getobject_test.go
index 14a8ac253e..f2b0ac80c3 100644
--- a/integrations/lfs_getobject_test.go
+++ b/tests/integration/lfs_getobject_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"archive/zip"
@@ -18,6 +18,7 @@ import (
 	"code.gitea.io/gitea/modules/lfs"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/routers/web"
+	"code.gitea.io/gitea/tests"
 
 	gzipp "github.com/klauspost/compress/gzip"
 	"github.com/stretchr/testify/assert"
@@ -81,7 +82,7 @@ func checkResponseTestContentEncoding(t *testing.T, content *[]byte, resp *httpt
 }
 
 func TestGetLFSSmall(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	content := []byte("A very small file\n")
 
 	resp := storeAndGetLfs(t, &content, nil, http.StatusOK)
@@ -89,7 +90,7 @@ func TestGetLFSSmall(t *testing.T) {
 }
 
 func TestGetLFSLarge(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	content := make([]byte, web.GzipMinSize*10)
 	for i := range content {
 		content[i] = byte(i % 256)
@@ -100,7 +101,7 @@ func TestGetLFSLarge(t *testing.T) {
 }
 
 func TestGetLFSGzip(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	b := make([]byte, web.GzipMinSize*10)
 	for i := range b {
 		b[i] = byte(i % 256)
@@ -116,7 +117,7 @@ func TestGetLFSGzip(t *testing.T) {
 }
 
 func TestGetLFSZip(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	b := make([]byte, web.GzipMinSize*10)
 	for i := range b {
 		b[i] = byte(i % 256)
@@ -134,7 +135,7 @@ func TestGetLFSZip(t *testing.T) {
 }
 
 func TestGetLFSRangeNo(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	content := []byte("123456789\n")
 
 	resp := storeAndGetLfs(t, &content, nil, http.StatusOK)
@@ -142,7 +143,7 @@ func TestGetLFSRangeNo(t *testing.T) {
 }
 
 func TestGetLFSRange(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	content := []byte("123456789\n")
 
 	tests := []struct {
diff --git a/integrations/lfs_local_endpoint_test.go b/tests/integration/lfs_local_endpoint_test.go
similarity index 96%
rename from integrations/lfs_local_endpoint_test.go
rename to tests/integration/lfs_local_endpoint_test.go
index 9de0ec18c9..88c08c63db 100644
--- a/integrations/lfs_local_endpoint_test.go
+++ b/tests/integration/lfs_local_endpoint_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -12,6 +12,7 @@ import (
 	"testing"
 
 	"code.gitea.io/gitea/modules/lfs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -22,7 +23,7 @@ func str2url(raw string) *url.URL {
 }
 
 func TestDetermineLocalEndpoint(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	root, _ := os.MkdirTemp("", "lfs_test")
 	defer os.RemoveAll(root)
diff --git a/integrations/links_test.go b/tests/integration/links_test.go
similarity index 96%
rename from integrations/links_test.go
rename to tests/integration/links_test.go
index d0cf978f65..4eb29f0cee 100644
--- a/integrations/links_test.go
+++ b/tests/integration/links_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -13,12 +13,13 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/test"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestLinksNoLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	links := []string{
 		"/explore/repos",
@@ -47,7 +48,7 @@ func TestLinksNoLogin(t *testing.T) {
 }
 
 func TestRedirectsNoLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	redirects := map[string]string{
 		"/user2/repo1/commits/master":                "/user2/repo1/commits/branch/master",
@@ -65,7 +66,7 @@ func TestRedirectsNoLogin(t *testing.T) {
 }
 
 func TestNoLoginNotExist(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	links := []string{
 		"/user5/repo4/projects",
@@ -169,7 +170,7 @@ func testLinksAsUser(userName string, t *testing.T) {
 }
 
 func TestLinksLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	testLinksAsUser("user2", t)
 }
diff --git a/integrations/migrate_test.go b/tests/integration/migrate_test.go
similarity index 99%
rename from integrations/migrate_test.go
rename to tests/integration/migrate_test.go
index d16f74ab6d..0fe4014344 100644
--- a/integrations/migrate_test.go
+++ b/tests/integration/migrate_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
diff --git a/integrations/migration-test/gitea-v1.6.4.mssql.sql.gz b/tests/integration/migration-test/gitea-v1.6.4.mssql.sql.gz
similarity index 100%
rename from integrations/migration-test/gitea-v1.6.4.mssql.sql.gz
rename to tests/integration/migration-test/gitea-v1.6.4.mssql.sql.gz
diff --git a/integrations/migration-test/gitea-v1.6.4.mysql.sql.gz b/tests/integration/migration-test/gitea-v1.6.4.mysql.sql.gz
similarity index 100%
rename from integrations/migration-test/gitea-v1.6.4.mysql.sql.gz
rename to tests/integration/migration-test/gitea-v1.6.4.mysql.sql.gz
diff --git a/integrations/migration-test/gitea-v1.6.4.postgres.sql.gz b/tests/integration/migration-test/gitea-v1.6.4.postgres.sql.gz
similarity index 100%
rename from integrations/migration-test/gitea-v1.6.4.postgres.sql.gz
rename to tests/integration/migration-test/gitea-v1.6.4.postgres.sql.gz
diff --git a/integrations/migration-test/gitea-v1.6.4.sqlite3.sql.gz b/tests/integration/migration-test/gitea-v1.6.4.sqlite3.sql.gz
similarity index 100%
rename from integrations/migration-test/gitea-v1.6.4.sqlite3.sql.gz
rename to tests/integration/migration-test/gitea-v1.6.4.sqlite3.sql.gz
diff --git a/integrations/migration-test/gitea-v1.7.0.mssql.sql.gz b/tests/integration/migration-test/gitea-v1.7.0.mssql.sql.gz
similarity index 100%
rename from integrations/migration-test/gitea-v1.7.0.mssql.sql.gz
rename to tests/integration/migration-test/gitea-v1.7.0.mssql.sql.gz
diff --git a/integrations/migration-test/gitea-v1.7.0.mysql.sql.gz b/tests/integration/migration-test/gitea-v1.7.0.mysql.sql.gz
similarity index 100%
rename from integrations/migration-test/gitea-v1.7.0.mysql.sql.gz
rename to tests/integration/migration-test/gitea-v1.7.0.mysql.sql.gz
diff --git a/integrations/migration-test/gitea-v1.7.0.postgres.sql.gz b/tests/integration/migration-test/gitea-v1.7.0.postgres.sql.gz
similarity index 100%
rename from integrations/migration-test/gitea-v1.7.0.postgres.sql.gz
rename to tests/integration/migration-test/gitea-v1.7.0.postgres.sql.gz
diff --git a/integrations/migration-test/gitea-v1.7.0.sqlite3.sql.gz b/tests/integration/migration-test/gitea-v1.7.0.sqlite3.sql.gz
similarity index 100%
rename from integrations/migration-test/gitea-v1.7.0.sqlite3.sql.gz
rename to tests/integration/migration-test/gitea-v1.7.0.sqlite3.sql.gz
diff --git a/integrations/migration-test/migration_test.go b/tests/integration/migration-test/migration_test.go
similarity index 90%
rename from integrations/migration-test/migration_test.go
rename to tests/integration/migration-test/migration_test.go
index 80093d66f1..b631168340 100644
--- a/integrations/migration-test/migration_test.go
+++ b/tests/integration/migration-test/migration_test.go
@@ -18,7 +18,6 @@ import (
 	"strings"
 	"testing"
 
-	"code.gitea.io/gitea/integrations"
 	"code.gitea.io/gitea/models/db"
 	"code.gitea.io/gitea/models/migrations"
 	"code.gitea.io/gitea/models/unittest"
@@ -27,6 +26,7 @@ import (
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 	"xorm.io/xorm"
@@ -35,21 +35,21 @@ import (
 var currentEngine *xorm.Engine
 
 func initMigrationTest(t *testing.T) func() {
-	deferFn := integrations.PrintCurrentTest(t, 2)
+	deferFn := tests.PrintCurrentTest(t, 2)
 	giteaRoot := base.SetupGiteaRoot()
 	if giteaRoot == "" {
-		integrations.Printf("Environment variable $GITEA_ROOT not set\n")
+		tests.Printf("Environment variable $GITEA_ROOT not set\n")
 		os.Exit(1)
 	}
 	setting.AppPath = path.Join(giteaRoot, "gitea")
 	if _, err := os.Stat(setting.AppPath); err != nil {
-		integrations.Printf("Could not find gitea binary at %s\n", setting.AppPath)
+		tests.Printf("Could not find gitea binary at %s\n", setting.AppPath)
 		os.Exit(1)
 	}
 
 	giteaConf := os.Getenv("GITEA_CONF")
 	if giteaConf == "" {
-		integrations.Printf("Environment variable $GITEA_CONF not set\n")
+		tests.Printf("Environment variable $GITEA_CONF not set\n")
 		os.Exit(1)
 	} else if !path.IsAbs(giteaConf) {
 		setting.CustomConf = path.Join(giteaRoot, giteaConf)
@@ -61,7 +61,7 @@ func initMigrationTest(t *testing.T) func() {
 
 	assert.True(t, len(setting.RepoRootPath) != 0)
 	assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
-	assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath))
+	assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath))
 	ownerDirs, err := os.ReadDir(setting.RepoRootPath)
 	if err != nil {
 		assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
@@ -89,7 +89,7 @@ func initMigrationTest(t *testing.T) func() {
 }
 
 func availableVersions() ([]string, error) {
-	migrationsDir, err := os.Open("integrations/migration-test")
+	migrationsDir, err := os.Open("tests/integration/migration-test")
 	if err != nil {
 		return nil, err
 	}
@@ -115,7 +115,7 @@ func availableVersions() ([]string, error) {
 }
 
 func readSQLFromFile(version string) (string, error) {
-	filename := fmt.Sprintf("integrations/migration-test/gitea-v%s.%s.sql.gz", version, setting.Database.Type)
+	filename := fmt.Sprintf("tests/integration/migration-test/gitea-v%s.%s.sql.gz", version, setting.Database.Type)
 
 	if _, err := os.Stat(filename); os.IsNotExist(err) {
 		return "", nil
@@ -144,7 +144,7 @@ func restoreOldDB(t *testing.T, version string) bool {
 	data, err := readSQLFromFile(version)
 	assert.NoError(t, err)
 	if len(data) == 0 {
-		integrations.Printf("No db found to restore for %s version: %s\n", setting.Database.Type, version)
+		tests.Printf("No db found to restore for %s version: %s\n", setting.Database.Type, version)
 		return false
 	}
 
@@ -286,8 +286,8 @@ func wrappedMigrate(x *xorm.Engine) error {
 }
 
 func doMigrationTest(t *testing.T, version string) {
-	defer integrations.PrintCurrentTest(t)()
-	integrations.Printf("Performing migration test for %s version: %s\n", setting.Database.Type, version)
+	defer tests.PrintCurrentTest(t)()
+	tests.Printf("Performing migration test for %s version: %s\n", setting.Database.Type, version)
 	if !restoreOldDB(t, version) {
 		return
 	}
@@ -325,11 +325,11 @@ func TestMigrations(t *testing.T) {
 	assert.NoError(t, err)
 
 	if len(versions) == 0 {
-		integrations.Printf("No old database versions available to migration test for %s\n", dialect)
+		tests.Printf("No old database versions available to migration test for %s\n", dialect)
 		return
 	}
 
-	integrations.Printf("Preparing to test %d migrations for %s\n", len(versions), dialect)
+	tests.Printf("Preparing to test %d migrations for %s\n", len(versions), dialect)
 	for _, version := range versions {
 		t.Run(fmt.Sprintf("Migrate-%s-%s", dialect, version), func(t *testing.T) {
 			doMigrationTest(t, version)
diff --git a/integrations/mirror_pull_test.go b/tests/integration/mirror_pull_test.go
similarity index 97%
rename from integrations/mirror_pull_test.go
rename to tests/integration/mirror_pull_test.go
index dcba17be49..707cf46fa0 100644
--- a/integrations/mirror_pull_test.go
+++ b/tests/integration/mirror_pull_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"context"
@@ -16,12 +16,13 @@ import (
 	"code.gitea.io/gitea/modules/repository"
 	mirror_service "code.gitea.io/gitea/services/mirror"
 	release_service "code.gitea.io/gitea/services/release"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestMirrorPull(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
diff --git a/integrations/mirror_push_test.go b/tests/integration/mirror_push_test.go
similarity index 98%
rename from integrations/mirror_push_test.go
rename to tests/integration/mirror_push_test.go
index 1af23d7837..f2adf5f5a3 100644
--- a/integrations/mirror_push_test.go
+++ b/tests/integration/mirror_push_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"context"
@@ -21,6 +21,7 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/services/migrations"
 	mirror_service "code.gitea.io/gitea/services/mirror"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -30,7 +31,7 @@ func TestMirrorPush(t *testing.T) {
 }
 
 func testMirrorPush(t *testing.T, u *url.URL) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	setting.Migrations.AllowLocalNetworks = true
 	assert.NoError(t, migrations.Init())
diff --git a/integrations/nonascii_branches_test.go b/tests/integration/nonascii_branches_test.go
similarity index 98%
rename from integrations/nonascii_branches_test.go
rename to tests/integration/nonascii_branches_test.go
index 038ada8ca2..ae69506f1b 100644
--- a/integrations/nonascii_branches_test.go
+++ b/tests/integration/nonascii_branches_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -10,6 +10,7 @@ import (
 	"path"
 	"testing"
 
+	"code.gitea.io/gitea/tests"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -197,7 +198,7 @@ func TestNonasciiBranches(t *testing.T) {
 		},
 	}
 
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user := "user2"
 	repo := "utf8"
diff --git a/integrations/oauth_test.go b/tests/integration/oauth_test.go
similarity index 96%
rename from integrations/oauth_test.go
rename to tests/integration/oauth_test.go
index c16bb4e24c..7fa26c8147 100644
--- a/integrations/oauth_test.go
+++ b/tests/integration/oauth_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
@@ -12,6 +12,7 @@ import (
 
 	"code.gitea.io/gitea/modules/json"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -19,20 +20,20 @@ import (
 const defaultAuthorize = "/login/oauth/authorize?client_id=da7da3ba-9a13-4167-856f-3899de0b0138&redirect_uri=a&response_type=code&state=thestate"
 
 func TestNoClientID(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequest(t, "GET", "/login/oauth/authorize")
 	ctx := loginUser(t, "user2")
 	ctx.MakeRequest(t, req, http.StatusBadRequest)
 }
 
 func TestLoginRedirect(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequest(t, "GET", "/login/oauth/authorize")
 	assert.Contains(t, MakeRequest(t, req, http.StatusSeeOther).Body.String(), "/user/login")
 }
 
 func TestShowAuthorize(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequest(t, "GET", defaultAuthorize)
 	ctx := loginUser(t, "user4")
 	resp := ctx.MakeRequest(t, req, http.StatusOK)
@@ -43,7 +44,7 @@ func TestShowAuthorize(t *testing.T) {
 }
 
 func TestRedirectWithExistingGrant(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequest(t, "GET", defaultAuthorize)
 	ctx := loginUser(t, "user1")
 	resp := ctx.MakeRequest(t, req, http.StatusSeeOther)
@@ -54,7 +55,7 @@ func TestRedirectWithExistingGrant(t *testing.T) {
 }
 
 func TestAccessTokenExchange(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
 		"grant_type":    "authorization_code",
 		"client_id":     "da7da3ba-9a13-4167-856f-3899de0b0138",
@@ -78,7 +79,7 @@ func TestAccessTokenExchange(t *testing.T) {
 }
 
 func TestAccessTokenExchangeWithoutPKCE(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequestWithJSON(t, "POST", "/login/oauth/access_token", map[string]string{
 		"grant_type":    "authorization_code",
 		"client_id":     "da7da3ba-9a13-4167-856f-3899de0b0138",
@@ -102,7 +103,7 @@ func TestAccessTokenExchangeWithoutPKCE(t *testing.T) {
 }
 
 func TestAccessTokenExchangeJSON(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequestWithJSON(t, "POST", "/login/oauth/access_token", map[string]string{
 		"grant_type":    "authorization_code",
 		"client_id":     "da7da3ba-9a13-4167-856f-3899de0b0138",
@@ -114,7 +115,7 @@ func TestAccessTokenExchangeJSON(t *testing.T) {
 }
 
 func TestAccessTokenExchangeWithInvalidCredentials(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	// invalid client id
 	req := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
 		"grant_type":    "authorization_code",
@@ -168,7 +169,7 @@ func TestAccessTokenExchangeWithInvalidCredentials(t *testing.T) {
 }
 
 func TestAccessTokenExchangeWithBasicAuth(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
 		"grant_type":    "authorization_code",
 		"redirect_uri":  "a",
@@ -210,7 +211,7 @@ func TestAccessTokenExchangeWithBasicAuth(t *testing.T) {
 }
 
 func TestRefreshTokenInvalidation(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	req := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
 		"grant_type":    "authorization_code",
 		"client_id":     "da7da3ba-9a13-4167-856f-3899de0b0138",
diff --git a/integrations/org_count_test.go b/tests/integration/org_count_test.go
similarity index 99%
rename from integrations/org_count_test.go
rename to tests/integration/org_count_test.go
index 2bffa90034..96f39924f1 100644
--- a/integrations/org_count_test.go
+++ b/tests/integration/org_count_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/url"
diff --git a/integrations/org_test.go b/tests/integration/org_test.go
similarity index 96%
rename from integrations/org_test.go
rename to tests/integration/org_test.go
index 9fb1175d7a..d04fcf7f57 100644
--- a/integrations/org_test.go
+++ b/tests/integration/org_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -13,12 +13,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestOrgRepos(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	var (
 		users = []string{"user1", "user2"}
@@ -48,7 +49,7 @@ func TestOrgRepos(t *testing.T) {
 }
 
 func TestLimitedOrg(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// not logged in user
 	req := NewRequest(t, "GET", "/limited_org")
@@ -78,7 +79,7 @@ func TestLimitedOrg(t *testing.T) {
 }
 
 func TestPrivateOrg(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// not logged in user
 	req := NewRequest(t, "GET", "/privated_org")
@@ -117,7 +118,7 @@ func TestPrivateOrg(t *testing.T) {
 }
 
 func TestOrgMembers(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// not logged in user
 	req := NewRequest(t, "GET", "/org/org25/members")
@@ -135,7 +136,7 @@ func TestOrgMembers(t *testing.T) {
 }
 
 func TestOrgRestrictedUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	// privated_org is a private org who has id 23
 	orgName := "privated_org"
@@ -195,7 +196,7 @@ func TestOrgRestrictedUser(t *testing.T) {
 }
 
 func TestTeamSearch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15})
 	org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 17})
diff --git a/integrations/private-testing.key b/tests/integration/private-testing.key
similarity index 100%
rename from integrations/private-testing.key
rename to tests/integration/private-testing.key
diff --git a/integrations/privateactivity_test.go b/tests/integration/privateactivity_test.go
similarity index 93%
rename from integrations/privateactivity_test.go
rename to tests/integration/privateactivity_test.go
index d91a1ddc30..3f352e49c6 100644
--- a/integrations/privateactivity_test.go
+++ b/tests/integration/privateactivity_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -14,6 +14,7 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -138,7 +139,7 @@ func testPrivateActivityHelperHasHeatmapContentFromSession(t *testing.T, session
 // check activity visibility if the visibility is enabled
 
 func TestPrivateActivityNoVisibleForPublic(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	visible := testPrivateActivityHelperHasVisibleActivitiesFromPublic(t)
@@ -147,7 +148,7 @@ func TestPrivateActivityNoVisibleForPublic(t *testing.T) {
 }
 
 func TestPrivateActivityNoVisibleForUserItself(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	session := loginUser(t, privateActivityTestUser)
@@ -157,7 +158,7 @@ func TestPrivateActivityNoVisibleForUserItself(t *testing.T) {
 }
 
 func TestPrivateActivityNoVisibleForOtherUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	session := loginUser(t, privateActivityTestOtherUser)
@@ -167,7 +168,7 @@ func TestPrivateActivityNoVisibleForOtherUser(t *testing.T) {
 }
 
 func TestPrivateActivityNoVisibleForAdmin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	session := loginUser(t, privateActivityTestAdmin)
@@ -179,7 +180,7 @@ func TestPrivateActivityNoVisibleForAdmin(t *testing.T) {
 // check activity visibility if the visibility is disabled
 
 func TestPrivateActivityYesInvisibleForPublic(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -189,7 +190,7 @@ func TestPrivateActivityYesInvisibleForPublic(t *testing.T) {
 }
 
 func TestPrivateActivityYesVisibleForUserItself(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -200,7 +201,7 @@ func TestPrivateActivityYesVisibleForUserItself(t *testing.T) {
 }
 
 func TestPrivateActivityYesInvisibleForOtherUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -211,7 +212,7 @@ func TestPrivateActivityYesInvisibleForOtherUser(t *testing.T) {
 }
 
 func TestPrivateActivityYesVisibleForAdmin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -224,7 +225,7 @@ func TestPrivateActivityYesVisibleForAdmin(t *testing.T) {
 // check heatmap visibility if the visibility is enabled
 
 func TestPrivateActivityNoHeatmapVisibleForPublic(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	visible := testPrivateActivityHelperHasVisibleHeatmapFromPublic(t)
@@ -233,7 +234,7 @@ func TestPrivateActivityNoHeatmapVisibleForPublic(t *testing.T) {
 }
 
 func TestPrivateActivityNoHeatmapVisibleForUserItselfAtProfile(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	session := loginUser(t, privateActivityTestUser)
@@ -243,7 +244,7 @@ func TestPrivateActivityNoHeatmapVisibleForUserItselfAtProfile(t *testing.T) {
 }
 
 func TestPrivateActivityNoHeatmapVisibleForUserItselfAtDashboard(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	session := loginUser(t, privateActivityTestUser)
@@ -253,7 +254,7 @@ func TestPrivateActivityNoHeatmapVisibleForUserItselfAtDashboard(t *testing.T) {
 }
 
 func TestPrivateActivityNoHeatmapVisibleForOtherUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	session := loginUser(t, privateActivityTestOtherUser)
@@ -263,7 +264,7 @@ func TestPrivateActivityNoHeatmapVisibleForOtherUser(t *testing.T) {
 }
 
 func TestPrivateActivityNoHeatmapVisibleForAdmin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	session := loginUser(t, privateActivityTestAdmin)
@@ -275,7 +276,7 @@ func TestPrivateActivityNoHeatmapVisibleForAdmin(t *testing.T) {
 // check heatmap visibility if the visibility is disabled
 
 func TestPrivateActivityYesHeatmapInvisibleForPublic(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -285,7 +286,7 @@ func TestPrivateActivityYesHeatmapInvisibleForPublic(t *testing.T) {
 }
 
 func TestPrivateActivityYesHeatmapVisibleForUserItselfAtProfile(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -296,7 +297,7 @@ func TestPrivateActivityYesHeatmapVisibleForUserItselfAtProfile(t *testing.T) {
 }
 
 func TestPrivateActivityYesHeatmapVisibleForUserItselfAtDashboard(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -307,7 +308,7 @@ func TestPrivateActivityYesHeatmapVisibleForUserItselfAtDashboard(t *testing.T)
 }
 
 func TestPrivateActivityYesHeatmapInvisibleForOtherUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -318,7 +319,7 @@ func TestPrivateActivityYesHeatmapInvisibleForOtherUser(t *testing.T) {
 }
 
 func TestPrivateActivityYesHeatmapVisibleForAdmin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -331,7 +332,7 @@ func TestPrivateActivityYesHeatmapVisibleForAdmin(t *testing.T) {
 // check heatmap api provides content if the visibility is enabled
 
 func TestPrivateActivityNoHeatmapHasContentForPublic(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	hasContent := testPrivateActivityHelperHasHeatmapContentFromPublic(t)
@@ -340,7 +341,7 @@ func TestPrivateActivityNoHeatmapHasContentForPublic(t *testing.T) {
 }
 
 func TestPrivateActivityNoHeatmapHasContentForUserItself(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	session := loginUser(t, privateActivityTestUser)
@@ -350,7 +351,7 @@ func TestPrivateActivityNoHeatmapHasContentForUserItself(t *testing.T) {
 }
 
 func TestPrivateActivityNoHeatmapHasContentForOtherUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	session := loginUser(t, privateActivityTestOtherUser)
@@ -360,7 +361,7 @@ func TestPrivateActivityNoHeatmapHasContentForOtherUser(t *testing.T) {
 }
 
 func TestPrivateActivityNoHeatmapHasContentForAdmin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 
 	session := loginUser(t, privateActivityTestAdmin)
@@ -373,7 +374,7 @@ func TestPrivateActivityNoHeatmapHasContentForAdmin(t *testing.T) {
 // this should be equal to the hidden heatmap at the UI
 
 func TestPrivateActivityYesHeatmapHasNoContentForPublic(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -383,7 +384,7 @@ func TestPrivateActivityYesHeatmapHasNoContentForPublic(t *testing.T) {
 }
 
 func TestPrivateActivityYesHeatmapHasNoContentForUserItself(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -394,7 +395,7 @@ func TestPrivateActivityYesHeatmapHasNoContentForUserItself(t *testing.T) {
 }
 
 func TestPrivateActivityYesHeatmapHasNoContentForOtherUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
@@ -405,7 +406,7 @@ func TestPrivateActivityYesHeatmapHasNoContentForOtherUser(t *testing.T) {
 }
 
 func TestPrivateActivityYesHeatmapHasNoContentForAdmin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testPrivateActivityDoSomethingForActionEntries(t)
 	testPrivateActivityHelperEnablePrivateActivity(t)
 
diff --git a/integrations/pull_compare_test.go b/tests/integration/pull_compare_test.go
similarity index 90%
rename from integrations/pull_compare_test.go
rename to tests/integration/pull_compare_test.go
index 1dec39a28f..7934b6e77c 100644
--- a/integrations/pull_compare_test.go
+++ b/tests/integration/pull_compare_test.go
@@ -2,17 +2,18 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
 	"testing"
 
+	"code.gitea.io/gitea/tests"
 	"github.com/stretchr/testify/assert"
 )
 
 func TestPullCompare(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 	req := NewRequest(t, "GET", "/user2/repo1/pulls")
diff --git a/integrations/pull_create_test.go b/tests/integration/pull_create_test.go
similarity index 98%
rename from integrations/pull_create_test.go
rename to tests/integration/pull_create_test.go
index 671b5e7551..24c73ab4e9 100644
--- a/integrations/pull_create_test.go
+++ b/tests/integration/pull_create_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -12,6 +12,7 @@ import (
 	"strings"
 	"testing"
 
+	"code.gitea.io/gitea/tests"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -135,7 +136,7 @@ func testDeleteRepository(t *testing.T, session *TestSession, ownerName, repoNam
 
 func TestPullBranchDelete(t *testing.T) {
 	onGiteaRun(t, func(t *testing.T, u *url.URL) {
-		defer prepareTestEnv(t)()
+		defer tests.PrepareTestEnv(t)()
 
 		session := loginUser(t, "user1")
 		testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
diff --git a/integrations/pull_merge_test.go b/tests/integration/pull_merge_test.go
similarity index 99%
rename from integrations/pull_merge_test.go
rename to tests/integration/pull_merge_test.go
index 1ae1ec6576..335dae4b38 100644
--- a/integrations/pull_merge_test.go
+++ b/tests/integration/pull_merge_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
diff --git a/integrations/pull_review_test.go b/tests/integration/pull_review_test.go
similarity index 84%
rename from integrations/pull_review_test.go
rename to tests/integration/pull_review_test.go
index d8f7b52d54..d713c0f858 100644
--- a/integrations/pull_review_test.go
+++ b/tests/integration/pull_review_test.go
@@ -1,15 +1,17 @@
 // Copyright 2019 The Gitea Authors. All rights reserved.
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
-package integrations
+package integration
 
 import (
 	"net/http"
 	"testing"
+
+	"code.gitea.io/gitea/tests"
 )
 
 func TestPullView_ReviewerMissed(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user1")
 
 	req := NewRequest(t, "GET", "/pulls")
diff --git a/integrations/pull_status_test.go b/tests/integration/pull_status_test.go
similarity index 99%
rename from integrations/pull_status_test.go
rename to tests/integration/pull_status_test.go
index d38d90169b..0f9cd41ec2 100644
--- a/integrations/pull_status_test.go
+++ b/tests/integration/pull_status_test.go
@@ -1,7 +1,7 @@
 // Copyright 2019 The Gitea Authors. All rights reserved.
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
-package integrations
+package integration
 
 import (
 	"fmt"
diff --git a/integrations/pull_update_test.go b/tests/integration/pull_update_test.go
similarity index 99%
rename from integrations/pull_update_test.go
rename to tests/integration/pull_update_test.go
index 475382c043..c08faaaeb6 100644
--- a/integrations/pull_update_test.go
+++ b/tests/integration/pull_update_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
diff --git a/integrations/release_test.go b/tests/integration/release_test.go
similarity index 94%
rename from integrations/release_test.go
rename to tests/integration/release_test.go
index 5c6290422d..2a52a5cde2 100644
--- a/integrations/release_test.go
+++ b/tests/integration/release_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -15,6 +15,7 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/test"
 	"code.gitea.io/gitea/modules/translation"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/PuerkitoBio/goquery"
 	"github.com/stretchr/testify/assert"
@@ -63,7 +64,7 @@ func checkLatestReleaseAndCount(t *testing.T, session *TestSession, repoURL, ver
 }
 
 func TestViewReleases(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 	req := NewRequest(t, "GET", "/user2/repo1/releases")
@@ -74,14 +75,14 @@ func TestViewReleases(t *testing.T) {
 }
 
 func TestViewReleasesNoLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequest(t, "GET", "/user2/repo1/releases")
 	MakeRequest(t, req, http.StatusOK)
 }
 
 func TestCreateRelease(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 	createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, false)
@@ -90,7 +91,7 @@ func TestCreateRelease(t *testing.T) {
 }
 
 func TestCreateReleasePreRelease(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 	createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", true, false)
@@ -99,7 +100,7 @@ func TestCreateReleasePreRelease(t *testing.T) {
 }
 
 func TestCreateReleaseDraft(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 	createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, true)
@@ -108,7 +109,7 @@ func TestCreateReleaseDraft(t *testing.T) {
 }
 
 func TestCreateReleasePaging(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	oldAPIDefaultNum := setting.API.DefaultPagingNum
 	defer func() {
@@ -132,7 +133,7 @@ func TestCreateReleasePaging(t *testing.T) {
 }
 
 func TestViewReleaseListNoLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 
@@ -158,7 +159,7 @@ func TestViewReleaseListNoLogin(t *testing.T) {
 }
 
 func TestViewReleaseListLogin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 
@@ -189,7 +190,7 @@ func TestViewReleaseListLogin(t *testing.T) {
 }
 
 func TestViewTagsList(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 
diff --git a/integrations/rename_branch_test.go b/tests/integration/rename_branch_test.go
similarity index 98%
rename from integrations/rename_branch_test.go
rename to tests/integration/rename_branch_test.go
index ad27869cde..9ea69702af 100644
--- a/integrations/rename_branch_test.go
+++ b/tests/integration/rename_branch_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
diff --git a/integrations/repo_activity_test.go b/tests/integration/repo_activity_test.go
similarity index 99%
rename from integrations/repo_activity_test.go
rename to tests/integration/repo_activity_test.go
index a10ec7f2d3..ea8845ac39 100644
--- a/integrations/repo_activity_test.go
+++ b/tests/integration/repo_activity_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
diff --git a/integrations/repo_branch_test.go b/tests/integration/repo_branch_test.go
similarity index 98%
rename from integrations/repo_branch_test.go
rename to tests/integration/repo_branch_test.go
index 74d85c5b1f..96ffa5a46e 100644
--- a/integrations/repo_branch_test.go
+++ b/tests/integration/repo_branch_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -14,6 +14,7 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/test"
 	"code.gitea.io/gitea/modules/translation"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -129,7 +130,7 @@ func testCreateBranches(t *testing.T, giteaURL *url.URL) {
 }
 
 func TestCreateBranchInvalidCSRF(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user2")
 	req := NewRequestWithValues(t, "POST", "user2/repo1/branches/_new/branch/master", map[string]string{
 		"_csrf":           "fake_csrf",
diff --git a/integrations/repo_commits_search_test.go b/tests/integration/repo_commits_search_test.go
similarity index 94%
rename from integrations/repo_commits_search_test.go
rename to tests/integration/repo_commits_search_test.go
index 0dc0588297..75e692f0ab 100644
--- a/integrations/repo_commits_search_test.go
+++ b/tests/integration/repo_commits_search_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -10,6 +10,7 @@ import (
 	"strings"
 	"testing"
 
+	"code.gitea.io/gitea/tests"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -26,7 +27,7 @@ func testRepoCommitsSearch(t *testing.T, query, commit string) {
 }
 
 func TestRepoCommitsSearch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	testRepoCommitsSearch(t, "e8eabd", "")
 	testRepoCommitsSearch(t, "38a9cb", "")
 	testRepoCommitsSearch(t, "6e8e", "6e8eabd9a7")
diff --git a/integrations/repo_commits_test.go b/tests/integration/repo_commits_test.go
similarity index 97%
rename from integrations/repo_commits_test.go
rename to tests/integration/repo_commits_test.go
index b18b35da1e..c9e7753596 100644
--- a/integrations/repo_commits_test.go
+++ b/tests/integration/repo_commits_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -13,12 +13,13 @@ import (
 	"code.gitea.io/gitea/modules/json"
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestRepoCommits(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
@@ -33,7 +34,7 @@ func TestRepoCommits(t *testing.T) {
 }
 
 func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
diff --git a/integrations/repo_fork_test.go b/tests/integration/repo_fork_test.go
similarity index 96%
rename from integrations/repo_fork_test.go
rename to tests/integration/repo_fork_test.go
index 17133621d6..4ab3577b54 100644
--- a/integrations/repo_fork_test.go
+++ b/tests/integration/repo_fork_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -12,6 +12,7 @@ import (
 
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -55,13 +56,13 @@ func testRepoFork(t *testing.T, session *TestSession, ownerName, repoName, forkO
 }
 
 func TestRepoFork(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user1")
 	testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
 }
 
 func TestRepoForkToOrg(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user2")
 	testRepoFork(t, session, "user2", "repo1", "user3", "repo1")
 
diff --git a/integrations/repo_generate_test.go b/tests/integration/repo_generate_test.go
similarity index 95%
rename from integrations/repo_generate_test.go
rename to tests/integration/repo_generate_test.go
index d34983f528..61a632721e 100644
--- a/integrations/repo_generate_test.go
+++ b/tests/integration/repo_generate_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -12,6 +12,7 @@ import (
 
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -56,13 +57,13 @@ func testRepoGenerate(t *testing.T, session *TestSession, templateOwnerName, tem
 }
 
 func TestRepoGenerate(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user1")
 	testRepoGenerate(t, session, "user27", "template1", "user1", "generated1")
 }
 
 func TestRepoGenerateToOrg(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user2")
 	testRepoGenerate(t, session, "user27", "template1", "user2", "generated2")
 }
diff --git a/integrations/repo_migrate_test.go b/tests/integration/repo_migrate_test.go
similarity index 94%
rename from integrations/repo_migrate_test.go
rename to tests/integration/repo_migrate_test.go
index 4e6923dd6f..c69a2642cb 100644
--- a/integrations/repo_migrate_test.go
+++ b/tests/integration/repo_migrate_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -11,6 +11,7 @@ import (
 	"testing"
 
 	"code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -39,7 +40,7 @@ func testRepoMigrate(t testing.TB, session *TestSession, cloneAddr, repoName str
 }
 
 func TestRepoMigrate(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user2")
 	testRepoMigrate(t, session, "https://github.com/go-gitea/test_repo.git", "git")
 }
diff --git a/integrations/repo_search_test.go b/tests/integration/repo_search_test.go
similarity index 96%
rename from integrations/repo_search_test.go
rename to tests/integration/repo_search_test.go
index a1cc5811b9..b20943c22a 100644
--- a/integrations/repo_search_test.go
+++ b/tests/integration/repo_search_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -11,6 +11,7 @@ import (
 	repo_model "code.gitea.io/gitea/models/repo"
 	code_indexer "code.gitea.io/gitea/modules/indexer/code"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/PuerkitoBio/goquery"
 	"github.com/stretchr/testify/assert"
@@ -26,7 +27,7 @@ func resultFilenames(t testing.TB, doc *HTMLDoc) []string {
 }
 
 func TestSearchRepo(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo, err := repo_model.GetRepositoryByOwnerAndName("user2", "repo1")
 	assert.NoError(t, err)
diff --git a/integrations/repo_tag_test.go b/tests/integration/repo_tag_test.go
similarity index 95%
rename from integrations/repo_tag_test.go
rename to tests/integration/repo_tag_test.go
index 8bb7c9f32a..a91f1fb209 100644
--- a/integrations/repo_tag_test.go
+++ b/tests/integration/repo_tag_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/url"
@@ -17,18 +17,19 @@ import (
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/services/release"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestCreateNewTagProtected(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
 
 	t.Run("API", func(t *testing.T) {
-		defer PrintCurrentTest(t)()
+		defer tests.PrintCurrentTest(t)()
 
 		err := release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-1", "first tag")
 		assert.NoError(t, err)
diff --git a/integrations/repo_test.go b/tests/integration/repo_test.go
similarity index 94%
rename from integrations/repo_test.go
rename to tests/integration/repo_test.go
index c2ac6183f0..8dfa9d08f1 100644
--- a/integrations/repo_test.go
+++ b/tests/integration/repo_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -13,13 +13,14 @@ import (
 	"time"
 
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/PuerkitoBio/goquery"
 	"github.com/stretchr/testify/assert"
 )
 
 func TestViewRepo(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequest(t, "GET", "/user2/repo1")
 	MakeRequest(t, req, http.StatusOK)
@@ -32,7 +33,7 @@ func TestViewRepo(t *testing.T) {
 }
 
 func testViewRepo(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequest(t, "GET", "/user3/repo3")
 	session := loginUser(t, "user2")
@@ -100,7 +101,7 @@ func TestViewRepo2(t *testing.T) {
 }
 
 func TestViewRepo3(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequest(t, "GET", "/user3/repo3")
 	session := loginUser(t, "user4")
@@ -108,7 +109,7 @@ func TestViewRepo3(t *testing.T) {
 }
 
 func TestViewRepo1CloneLinkAnonymous(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequest(t, "GET", "/user2/repo1")
 	resp := MakeRequest(t, req, http.StatusOK)
@@ -122,7 +123,7 @@ func TestViewRepo1CloneLinkAnonymous(t *testing.T) {
 }
 
 func TestViewRepo1CloneLinkAuthorized(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
@@ -140,7 +141,7 @@ func TestViewRepo1CloneLinkAuthorized(t *testing.T) {
 }
 
 func TestViewRepoWithSymlinks(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
@@ -168,7 +169,7 @@ func TestViewAsRepoAdmin(t *testing.T) {
 		"user2": true,
 		"user4": false,
 	} {
-		defer prepareTestEnv(t)()
+		defer tests.PrepareTestEnv(t)()
 
 		session := loginUser(t, user)
 
diff --git a/integrations/repo_topic_test.go b/tests/integration/repo_topic_test.go
similarity index 94%
rename from integrations/repo_topic_test.go
rename to tests/integration/repo_topic_test.go
index e049afdd7c..5ff0c8273a 100644
--- a/integrations/repo_topic_test.go
+++ b/tests/integration/repo_topic_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -10,12 +10,13 @@ import (
 	"testing"
 
 	api "code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestTopicSearch(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	searchURL, _ := url.Parse("/explore/topics/search")
 	var topics struct {
 		TopicNames []*api.TopicResponse `json:"topics"`
diff --git a/integrations/repo_watch_test.go b/tests/integration/repo_watch_test.go
similarity index 97%
rename from integrations/repo_watch_test.go
rename to tests/integration/repo_watch_test.go
index 2ff3b26361..152600bf29 100644
--- a/integrations/repo_watch_test.go
+++ b/tests/integration/repo_watch_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/url"
diff --git a/integrations/repofiles_delete_test.go b/tests/integration/repofiles_delete_test.go
similarity index 99%
rename from integrations/repofiles_delete_test.go
rename to tests/integration/repofiles_delete_test.go
index a6c2484a56..f594efdeeb 100644
--- a/integrations/repofiles_delete_test.go
+++ b/tests/integration/repofiles_delete_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/url"
diff --git a/integrations/repofiles_update_test.go b/tests/integration/repofiles_update_test.go
similarity index 99%
rename from integrations/repofiles_update_test.go
rename to tests/integration/repofiles_update_test.go
index ac9b0509ea..c62c49eeeb 100644
--- a/integrations/repofiles_update_test.go
+++ b/tests/integration/repofiles_update_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/url"
diff --git a/integrations/setting_test.go b/tests/integration/setting_test.go
similarity index 95%
rename from integrations/setting_test.go
rename to tests/integration/setting_test.go
index 3852eb4955..6273545c23 100644
--- a/integrations/setting_test.go
+++ b/tests/integration/setting_test.go
@@ -2,19 +2,20 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
 	"testing"
 
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestSettingShowUserEmailExplore(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	showUserEmail := setting.UI.ShowUserEmail
 	setting.UI.ShowUserEmail = true
@@ -42,7 +43,7 @@ func TestSettingShowUserEmailExplore(t *testing.T) {
 }
 
 func TestSettingShowUserEmailProfile(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	showUserEmail := setting.UI.ShowUserEmail
 	setting.UI.ShowUserEmail = true
@@ -80,7 +81,7 @@ func TestSettingShowUserEmailProfile(t *testing.T) {
 }
 
 func TestSettingLandingPage(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	landingPage := setting.LandingPageURL
 
diff --git a/integrations/signin_test.go b/tests/integration/signin_test.go
similarity index 95%
rename from integrations/signin_test.go
rename to tests/integration/signin_test.go
index 568ceb40ca..7dc078e274 100644
--- a/integrations/signin_test.go
+++ b/tests/integration/signin_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -12,6 +12,7 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/translation"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -32,7 +33,7 @@ func testLoginFailed(t *testing.T, username, password, message string) {
 }
 
 func TestSignin(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
diff --git a/integrations/signout_test.go b/tests/integration/signout_test.go
similarity index 87%
rename from integrations/signout_test.go
rename to tests/integration/signout_test.go
index 8ef97e89c5..1f1346a5c3 100644
--- a/integrations/signout_test.go
+++ b/tests/integration/signout_test.go
@@ -2,15 +2,17 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
 	"testing"
+
+	"code.gitea.io/gitea/tests"
 )
 
 func TestSignOut(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
diff --git a/integrations/signup_test.go b/tests/integration/signup_test.go
similarity index 94%
rename from integrations/signup_test.go
rename to tests/integration/signup_test.go
index 071ece9fa1..1c598fd0d1 100644
--- a/integrations/signup_test.go
+++ b/tests/integration/signup_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -14,12 +14,13 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/translation"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestSignup(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	setting.Service.EnableCaptcha = false
 
@@ -37,7 +38,7 @@ func TestSignup(t *testing.T) {
 }
 
 func TestSignupAsRestricted(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	setting.Service.EnableCaptcha = false
 	setting.Service.DefaultUserIsRestricted = true
@@ -59,7 +60,7 @@ func TestSignupAsRestricted(t *testing.T) {
 }
 
 func TestSignupEmail(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	setting.Service.EnableCaptcha = false
 
diff --git a/integrations/ssh_key_test.go b/tests/integration/ssh_key_test.go
similarity index 99%
rename from integrations/ssh_key_test.go
rename to tests/integration/ssh_key_test.go
index e0ff13543e..65d9b84404 100644
--- a/integrations/ssh_key_test.go
+++ b/tests/integration/ssh_key_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
diff --git a/integrations/timetracking_test.go b/tests/integration/timetracking_test.go
similarity index 94%
rename from integrations/timetracking_test.go
rename to tests/integration/timetracking_test.go
index 17e9174e5d..54b81ff3bc 100644
--- a/integrations/timetracking_test.go
+++ b/tests/integration/timetracking_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -11,26 +11,27 @@ import (
 	"time"
 
 	"code.gitea.io/gitea/modules/test"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestViewTimetrackingControls(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user2")
 	testViewTimetrackingControls(t, session, "user2", "repo1", "1", true)
 	// user2/repo1
 }
 
 func TestNotViewTimetrackingControls(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user5")
 	testViewTimetrackingControls(t, session, "user2", "repo1", "1", false)
 	// user2/repo1
 }
 
 func TestViewTimetrackingControlsDisabled(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	session := loginUser(t, "user2")
 	testViewTimetrackingControls(t, session, "user3", "repo3", "1", false)
 }
diff --git a/integrations/user_avatar_test.go b/tests/integration/user_avatar_test.go
similarity index 98%
rename from integrations/user_avatar_test.go
rename to tests/integration/user_avatar_test.go
index ee532bb64a..35be840c29 100644
--- a/integrations/user_avatar_test.go
+++ b/tests/integration/user_avatar_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"bytes"
diff --git a/integrations/user_test.go b/tests/integration/user_test.go
similarity index 97%
rename from integrations/user_test.go
rename to tests/integration/user_test.go
index b0c1cd42eb..110f5c89bf 100644
--- a/integrations/user_test.go
+++ b/tests/integration/user_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -15,19 +15,20 @@ import (
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/test"
 	"code.gitea.io/gitea/modules/translation"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestViewUser(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	req := NewRequest(t, "GET", "/user2")
 	MakeRequest(t, req, http.StatusOK)
 }
 
 func TestRenameUsername(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 	req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{
@@ -43,7 +44,7 @@ func TestRenameUsername(t *testing.T) {
 }
 
 func TestRenameInvalidUsername(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	invalidUsernames := []string{
 		"%2f*",
@@ -75,7 +76,7 @@ func TestRenameInvalidUsername(t *testing.T) {
 }
 
 func TestRenameReservedUsername(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	reservedUsernames := []string{
 		".",
@@ -139,7 +140,7 @@ func TestRenameReservedUsername(t *testing.T) {
 }
 
 func TestExportUserGPGKeys(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	// Export empty key list
 	testExportUserGPGKeys(t, "user1", `-----BEGIN PGP PUBLIC KEY BLOCK-----
 Note: This user hasn't uploaded any GPG keys.
@@ -227,7 +228,7 @@ func testExportUserGPGKeys(t *testing.T, user, expected string) {
 }
 
 func TestListStopWatches(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
diff --git a/integrations/version_test.go b/tests/integration/version_test.go
similarity index 87%
rename from integrations/version_test.go
rename to tests/integration/version_test.go
index a1d2f6c882..83be62d3f4 100644
--- a/integrations/version_test.go
+++ b/tests/integration/version_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -10,12 +10,13 @@ import (
 
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestVersion(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	setting.AppVer = "test-version-1"
 	req := NewRequest(t, "GET", "/api/v1/version")
diff --git a/integrations/view_test.go b/tests/integration/view_test.go
similarity index 89%
rename from integrations/view_test.go
rename to tests/integration/view_test.go
index 180cf2e50a..63544dbe35 100644
--- a/integrations/view_test.go
+++ b/tests/integration/view_test.go
@@ -2,17 +2,18 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
 	"testing"
 
+	"code.gitea.io/gitea/tests"
 	"github.com/stretchr/testify/assert"
 )
 
 func TestRenderFileSVGIsInImgTag(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	session := loginUser(t, "user2")
 
diff --git a/integrations/webfinger_test.go b/tests/integration/webfinger_test.go
similarity index 96%
rename from integrations/webfinger_test.go
rename to tests/integration/webfinger_test.go
index 3574941e42..bb3447c809 100644
--- a/integrations/webfinger_test.go
+++ b/tests/integration/webfinger_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"fmt"
@@ -13,12 +13,13 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestWebfinger(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 
 	setting.Federation.Enabled = true
 	defer func() {
diff --git a/integrations/xss_test.go b/tests/integration/xss_test.go
similarity index 93%
rename from integrations/xss_test.go
rename to tests/integration/xss_test.go
index d5ce94b0c6..53b23072ad 100644
--- a/integrations/xss_test.go
+++ b/tests/integration/xss_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package integration
 
 import (
 	"net/http"
@@ -10,12 +10,13 @@ import (
 
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/tests"
 
 	"github.com/stretchr/testify/assert"
 )
 
 func TestXSSUserFullName(t *testing.T) {
-	defer prepareTestEnv(t)()
+	defer tests.PrepareTestEnv(t)()
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 	const fullName = `name & <script class="evil">alert('Oh no!');</script>`
 
diff --git a/integrations/mssql.ini.tmpl b/tests/mssql.ini.tmpl
similarity index 71%
rename from integrations/mssql.ini.tmpl
rename to tests/mssql.ini.tmpl
index d4d1517011..9cec6169f9 100644
--- a/integrations/mssql.ini.tmpl
+++ b/tests/mssql.ini.tmpl
@@ -11,11 +11,11 @@ SSL_MODE = disable
 
 [indexer]
 REPO_INDEXER_ENABLED = true
-REPO_INDEXER_PATH = integrations/gitea-integration-mssql/indexers/repos.bleve
+REPO_INDEXER_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/indexers/repos.bleve
 
 [queue.issue_indexer]
-PATH = integrations/gitea-integration-mssql/indexers/issues.bleve
-DATADIR = integrations/gitea-integration-mssql/indexers/issues.queue
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/indexers/issues.bleve
+DATADIR = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/indexers/issues.queue
 
 [queue]
 TYPE = immediate
@@ -27,13 +27,13 @@ TYPE = immediate
 TYPE = immediate
 
 [repository]
-ROOT = {{REPO_TEST_DIR}}integrations/gitea-integration-mssql/gitea-repositories
+ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/gitea-repositories
 
 [repository.local]
-LOCAL_COPY_PATH = integrations/gitea-integration-mssql/tmp/local-repo
+LOCAL_COPY_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/tmp/local-repo
 
 [repository.upload]
-TEMP_PATH = integrations/gitea-integration-mssql/tmp/uploads
+TEMP_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/tmp/uploads
 
 [repository.signing]
 SIGNING_KEY = none
@@ -49,17 +49,17 @@ START_SSH_SERVER = true
 LFS_START_SERVER = true
 OFFLINE_MODE     = false
 LFS_JWT_SECRET   = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w
-APP_DATA_PATH    = integrations/gitea-integration-mssql/data
+APP_DATA_PATH    = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/data
 BUILTIN_SSH_SERVER_USER = git
 SSH_TRUSTED_USER_CA_KEYS = ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCb4DC1dMFnJ6pXWo7GMxTchtzmJHYzfN6sZ9FAPFR4ijMLfGki+olvOMO5Fql1/yGnGfbELQa1S6y4shSvj/5K+zUFScmEXYf3Gcr87RqilLkyk16RS+cHNB1u87xTHbETaa3nyCJeGQRpd4IQ4NKob745mwDZ7jQBH8AZEng50Oh8y8fi8skBBBzaYp1ilgvzG740L7uex6fHV62myq0SXeCa+oJUjq326FU8y+Vsa32H8A3e7tOgXZPdt2TVNltx2S9H2WO8RMi7LfaSwARNfy1zu+bfR50r6ef8Yx5YKCMz4wWb1SHU1GS800mjOjlInLQORYRNMlSwR1+vLlVDciOqFapDSbj+YOVOawR0R1aqlSKpZkt33DuOBPx9qe6CVnIi7Z+Px/KqM+OLCzlLY/RS+LbxQpDWcfTVRiP+S5qRTcE3M3UioN/e0BE/1+MpX90IGpvVkA63ILYbKEa4bM3ASL7ChTCr6xN5XT+GpVJveFKK1cfNx9ExHI4rzYE=
 
 [attachment]
-PATH = integrations/gitea-integration-mssql/data/attachments
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/data/attachments
 
 [mailer]
 ENABLED = true
 MAILER_TYPE = dummy
-FROM = mssql-integration-test@gitea.io
+FROM = mssql-{{TEST_TYPE}}-test@gitea.io
 
 [service]
 REGISTER_EMAIL_CONFIRM            = false
@@ -76,15 +76,15 @@ ENABLE_NOTIFY_MAIL                = true
 [picture]
 DISABLE_GRAVATAR              = false
 ENABLE_FEDERATED_AVATAR       = false
-AVATAR_UPLOAD_PATH            = integrations/gitea-integration-mssql/data/avatars
-REPOSITORY_AVATAR_UPLOAD_PATH = integrations/gitea-integration-mssql/data/repo-avatars
+AVATAR_UPLOAD_PATH            = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/data/avatars
+REPOSITORY_AVATAR_UPLOAD_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/data/repo-avatars
 
 [session]
 PROVIDER        = file
-PROVIDER_CONFIG = integrations/gitea-integration-mssql/data/sessions
+PROVIDER_CONFIG = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/data/sessions
 
 [log]
-MODE                 = test,file
+MODE                 = {{TEST_LOGGER}}
 ROOT_PATH            = {{REPO_TEST_DIR}}mssql-log
 ROUTER               = ,
 XORM                 = file
@@ -104,7 +104,7 @@ SECRET_KEY     = 9pCviYTWSb
 INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ
 
 [lfs]
-PATH = integrations/gitea-integration-mssql/data/lfs
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/data/lfs
 
 [packages]
 ENABLED = true
diff --git a/integrations/mysql.ini.tmpl b/tests/mysql.ini.tmpl
similarity index 82%
rename from integrations/mysql.ini.tmpl
rename to tests/mysql.ini.tmpl
index 8f610326e2..24a9a02dc4 100644
--- a/integrations/mysql.ini.tmpl
+++ b/tests/mysql.ini.tmpl
@@ -11,12 +11,12 @@ SSL_MODE = disable
 
 [indexer]
 REPO_INDEXER_ENABLED = true
-REPO_INDEXER_PATH = integrations/gitea-integration-mysql/indexers/repos.bleve
+REPO_INDEXER_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/indexers/repos.bleve
 
 [queue.issue_indexer]
 TYPE = elasticsearch
 CONN_STR = http://elastic:changeme@elasticsearch:9200
-DATADIR = integrations/gitea-integration-mysql/indexers/issues.queue
+DATADIR = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/indexers/issues.queue
 
 [queue]
 TYPE = immediate
@@ -28,13 +28,13 @@ TYPE = immediate
 TYPE = immediate
 
 [repository]
-ROOT = {{REPO_TEST_DIR}}integrations/gitea-integration-mysql/gitea-repositories
+ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/gitea-repositories
 
 [repository.local]
-LOCAL_COPY_PATH = integrations/gitea-integration-mysql/tmp/local-repo
+LOCAL_COPY_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/tmp/local-repo
 
 [repository.upload]
-TEMP_PATH = integrations/gitea-integration-mysql/tmp/uploads
+TEMP_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/tmp/uploads
 
 [repository.signing]
 SIGNING_KEY = none
@@ -46,7 +46,7 @@ ROOT_URL         = http://localhost:3001/
 DISABLE_SSH      = false
 SSH_LISTEN_HOST  = localhost
 SSH_PORT         = 2201
-APP_DATA_PATH    = integrations/gitea-integration-mysql/data
+APP_DATA_PATH    = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/data
 BUILTIN_SSH_SERVER_USER = git
 START_SSH_SERVER = true
 OFFLINE_MODE     = false
@@ -80,7 +80,7 @@ MINIO_USE_SSL = false
 [mailer]
 ENABLED = true
 MAILER_TYPE = dummy
-FROM = mysql-integration-test@gitea.io
+FROM = mysql-{{TEST_TYPE}}-test@gitea.io
 
 [service]
 REGISTER_EMAIL_CONFIRM            = false
@@ -100,10 +100,10 @@ ENABLE_FEDERATED_AVATAR       = false
 
 [session]
 PROVIDER        = file
-PROVIDER_CONFIG = integrations/gitea-integration-mysql/data/sessions
+PROVIDER_CONFIG = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/data/sessions
 
 [log]
-MODE                 = test,file
+MODE                 = {{TEST_LOGGER}}
 ROOT_PATH            = {{REPO_TEST_DIR}}mysql-log
 ROUTER               = ,
 XORM                 = file
diff --git a/integrations/mysql8.ini.tmpl b/tests/mysql8.ini.tmpl
similarity index 71%
rename from integrations/mysql8.ini.tmpl
rename to tests/mysql8.ini.tmpl
index 5133058237..f290efe1dc 100644
--- a/integrations/mysql8.ini.tmpl
+++ b/tests/mysql8.ini.tmpl
@@ -11,11 +11,11 @@ SSL_MODE = disable
 
 [indexer]
 REPO_INDEXER_ENABLED = true
-REPO_INDEXER_PATH = integrations/gitea-integration-mysql8/indexers/repos.bleve
+REPO_INDEXER_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/indexers/repos.bleve
 
 [queue.issue_indexer]
-PATH = integrations/gitea-integration-mysql8/indexers/issues.bleve
-DATADIR = integrations/gitea-integration-mysql8/indexers/issues.queue
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/indexers/issues.bleve
+DATADIR = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/indexers/issues.queue
 
 [queue]
 TYPE = immediate
@@ -27,13 +27,13 @@ TYPE = immediate
 TYPE = immediate
 
 [repository]
-ROOT = {{REPO_TEST_DIR}}integrations/gitea-integration-mysql8/gitea-repositories
+ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/gitea-repositories
 
 [repository.local]
-LOCAL_COPY_PATH = integrations/gitea-integration-mysql8/tmp/local-repo
+LOCAL_COPY_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/tmp/local-repo
 
 [repository.upload]
-TEMP_PATH = integrations/gitea-integration-mysql8/tmp/uploads
+TEMP_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/tmp/uploads
 
 [repository.signing]
 SIGNING_KEY = none
@@ -49,12 +49,12 @@ START_SSH_SERVER = true
 LFS_START_SERVER = true
 OFFLINE_MODE     = false
 LFS_JWT_SECRET   = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w
-APP_DATA_PATH    = integrations/gitea-integration-mysql8/data
+APP_DATA_PATH    = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data
 BUILTIN_SSH_SERVER_USER = git
 SSH_TRUSTED_USER_CA_KEYS = ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCb4DC1dMFnJ6pXWo7GMxTchtzmJHYzfN6sZ9FAPFR4ijMLfGki+olvOMO5Fql1/yGnGfbELQa1S6y4shSvj/5K+zUFScmEXYf3Gcr87RqilLkyk16RS+cHNB1u87xTHbETaa3nyCJeGQRpd4IQ4NKob745mwDZ7jQBH8AZEng50Oh8y8fi8skBBBzaYp1ilgvzG740L7uex6fHV62myq0SXeCa+oJUjq326FU8y+Vsa32H8A3e7tOgXZPdt2TVNltx2S9H2WO8RMi7LfaSwARNfy1zu+bfR50r6ef8Yx5YKCMz4wWb1SHU1GS800mjOjlInLQORYRNMlSwR1+vLlVDciOqFapDSbj+YOVOawR0R1aqlSKpZkt33DuOBPx9qe6CVnIi7Z+Px/KqM+OLCzlLY/RS+LbxQpDWcfTVRiP+S5qRTcE3M3UioN/e0BE/1+MpX90IGpvVkA63ILYbKEa4bM3ASL7ChTCr6xN5XT+GpVJveFKK1cfNx9ExHI4rzYE=
 
 [attachment]
-PATH = integrations/gitea-integration-mysql8/data/attachments
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data/attachments
 
 [mailer]
 ENABLED = false
@@ -73,15 +73,15 @@ NO_REPLY_ADDRESS                  = noreply.example.org
 [picture]
 DISABLE_GRAVATAR              = false
 ENABLE_FEDERATED_AVATAR       = false
-AVATAR_UPLOAD_PATH            = integrations/gitea-integration-mysql8/data/avatars
-REPOSITORY_AVATAR_UPLOAD_PATH = integrations/gitea-integration-mysql8/data/repo-avatars
+AVATAR_UPLOAD_PATH            = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data/avatars
+REPOSITORY_AVATAR_UPLOAD_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data/repo-avatars
 
 [session]
 PROVIDER = file
-PROVIDER_CONFIG = integrations/gitea-integration-mysql8/data/sessions
+PROVIDER_CONFIG = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data/sessions
 
 [log]
-MODE                 = test,file
+MODE                 = {{TEST_LOGGER}}
 ROOT_PATH            = {{REPO_TEST_DIR}}mysql8-log
 ROUTER               = ,
 XORM                 = file
@@ -101,7 +101,7 @@ SECRET_KEY     = 9pCviYTWSb
 INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ
 
 [lfs]
-PATH = integrations/gitea-integration-mysql8/data/lfs
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data/lfs
 
 [packages]
 ENABLED = true
diff --git a/integrations/pgsql.ini.tmpl b/tests/pgsql.ini.tmpl
similarity index 71%
rename from integrations/pgsql.ini.tmpl
rename to tests/pgsql.ini.tmpl
index 15cd6a057b..c39b6a79c3 100644
--- a/integrations/pgsql.ini.tmpl
+++ b/tests/pgsql.ini.tmpl
@@ -12,11 +12,11 @@ SSL_MODE = disable
 
 [indexer]
 REPO_INDEXER_ENABLED = true
-REPO_INDEXER_PATH = integrations/gitea-integration-pgsql/indexers/repos.bleve
+REPO_INDEXER_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/indexers/repos.bleve
 
 [queue.issue_indexer]
-PATH = integrations/gitea-integration-pgsql/indexers/issues.bleve
-DATADIR = integrations/gitea-integration-pgsql/indexers/issues.queue
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/indexers/issues.bleve
+DATADIR = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/indexers/issues.queue
 
 [queue]
 TYPE = immediate
@@ -28,13 +28,13 @@ TYPE = immediate
 TYPE = immediate
 
 [repository]
-ROOT = {{REPO_TEST_DIR}}integrations/gitea-integration-pgsql/gitea-repositories
+ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/gitea-repositories
 
 [repository.local]
-LOCAL_COPY_PATH = integrations/gitea-integration-pgsql/tmp/local-repo
+LOCAL_COPY_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/tmp/local-repo
 
 [repository.upload]
-TEMP_PATH = integrations/gitea-integration-pgsql/tmp/uploads
+TEMP_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/tmp/uploads
 
 [repository.signing]
 SIGNING_KEY = none
@@ -50,17 +50,17 @@ START_SSH_SERVER = true
 LFS_START_SERVER = true
 OFFLINE_MODE     = false
 LFS_JWT_SECRET   = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w
-APP_DATA_PATH    = integrations/gitea-integration-pgsql/data
+APP_DATA_PATH    = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/data
 BUILTIN_SSH_SERVER_USER = git
 SSH_TRUSTED_USER_CA_KEYS = ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCb4DC1dMFnJ6pXWo7GMxTchtzmJHYzfN6sZ9FAPFR4ijMLfGki+olvOMO5Fql1/yGnGfbELQa1S6y4shSvj/5K+zUFScmEXYf3Gcr87RqilLkyk16RS+cHNB1u87xTHbETaa3nyCJeGQRpd4IQ4NKob745mwDZ7jQBH8AZEng50Oh8y8fi8skBBBzaYp1ilgvzG740L7uex6fHV62myq0SXeCa+oJUjq326FU8y+Vsa32H8A3e7tOgXZPdt2TVNltx2S9H2WO8RMi7LfaSwARNfy1zu+bfR50r6ef8Yx5YKCMz4wWb1SHU1GS800mjOjlInLQORYRNMlSwR1+vLlVDciOqFapDSbj+YOVOawR0R1aqlSKpZkt33DuOBPx9qe6CVnIi7Z+Px/KqM+OLCzlLY/RS+LbxQpDWcfTVRiP+S5qRTcE3M3UioN/e0BE/1+MpX90IGpvVkA63ILYbKEa4bM3ASL7ChTCr6xN5XT+GpVJveFKK1cfNx9ExHI4rzYE=
 
 [attachment]
-PATH = integrations/gitea-integration-pgsql/data/attachments
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/data/attachments
 
 [mailer]
 ENABLED = true
 MAILER_TYPE = dummy
-FROM = pgsql-integration-test@gitea.io
+FROM = pgsql-{{TEST_TYPE}}-test@gitea.io
 
 [service]
 REGISTER_EMAIL_CONFIRM            = false
@@ -77,15 +77,15 @@ ENABLE_NOTIFY_MAIL                = true
 [picture]
 DISABLE_GRAVATAR              = false
 ENABLE_FEDERATED_AVATAR       = false
-AVATAR_UPLOAD_PATH            = integrations/gitea-integration-pgsql/data/avatars
-REPOSITORY_AVATAR_UPLOAD_PATH = integrations/gitea-integration-pgsql/data/repo-avatars
+AVATAR_UPLOAD_PATH            = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/data/avatars
+REPOSITORY_AVATAR_UPLOAD_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/data/repo-avatars
 
 [session]
 PROVIDER        = file
-PROVIDER_CONFIG = integrations/gitea-integration-pgsql/data/sessions
+PROVIDER_CONFIG = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/data/sessions
 
 [log]
-MODE                 = test,file
+MODE                 = {{TEST_LOGGER}}
 ROOT_PATH            = {{REPO_TEST_DIR}}pgsql-log
 ROUTER               = ,
 XORM                 = file
@@ -105,7 +105,7 @@ SECRET_KEY     = 9pCviYTWSb
 INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ
 
 [lfs]
-PATH = integrations/gitea-integration-pgsql/data/lfs
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/data/lfs
 
 [packages]
 ENABLED = true
diff --git a/integrations/sqlite.ini.tmpl b/tests/sqlite.ini.tmpl
similarity index 68%
rename from integrations/sqlite.ini.tmpl
rename to tests/sqlite.ini.tmpl
index fa57e1aa96..f5e8895e06 100644
--- a/integrations/sqlite.ini.tmpl
+++ b/tests/sqlite.ini.tmpl
@@ -3,15 +3,15 @@ RUN_MODE = prod
 
 [database]
 DB_TYPE = sqlite3
-PATH    = integrations/gitea-integration-sqlite/gitea.db
+PATH    = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/gitea.db
 
 [indexer]
 REPO_INDEXER_ENABLED = true
-REPO_INDEXER_PATH    = integrations/gitea-integration-sqlite/indexers/repos.bleve
+REPO_INDEXER_PATH    = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/indexers/repos.bleve
 
 [queue.issue_indexer]
-PATH   = integrations/gitea-integration-sqlite/indexers/issues.bleve
-DATADIR = integrations/gitea-integration-sqlite/indexers/issues.queue
+PATH   = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/indexers/issues.bleve
+DATADIR = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/indexers/issues.queue
 
 [queue]
 TYPE = immediate
@@ -23,13 +23,13 @@ TYPE = immediate
 TYPE = immediate
 
 [repository]
-ROOT = {{REPO_TEST_DIR}}integrations/gitea-integration-sqlite/gitea-repositories
+ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/gitea-repositories
 
 [repository.local]
-LOCAL_COPY_PATH = integrations/gitea-integration-sqlite/tmp/local-repo
+LOCAL_COPY_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/tmp/local-repo
 
 [repository.upload]
-TEMP_PATH = integrations/gitea-integration-sqlite/tmp/uploads
+TEMP_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/tmp/uploads
 
 [repository.signing]
 SIGNING_KEY = none
@@ -45,18 +45,18 @@ START_SSH_SERVER = true
 LFS_START_SERVER = true
 OFFLINE_MODE     = false
 LFS_JWT_SECRET   = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w
-APP_DATA_PATH    = integrations/gitea-integration-sqlite/data
+APP_DATA_PATH    = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/data
 ENABLE_GZIP      = true
 BUILTIN_SSH_SERVER_USER = git
 SSH_TRUSTED_USER_CA_KEYS = ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCb4DC1dMFnJ6pXWo7GMxTchtzmJHYzfN6sZ9FAPFR4ijMLfGki+olvOMO5Fql1/yGnGfbELQa1S6y4shSvj/5K+zUFScmEXYf3Gcr87RqilLkyk16RS+cHNB1u87xTHbETaa3nyCJeGQRpd4IQ4NKob745mwDZ7jQBH8AZEng50Oh8y8fi8skBBBzaYp1ilgvzG740L7uex6fHV62myq0SXeCa+oJUjq326FU8y+Vsa32H8A3e7tOgXZPdt2TVNltx2S9H2WO8RMi7LfaSwARNfy1zu+bfR50r6ef8Yx5YKCMz4wWb1SHU1GS800mjOjlInLQORYRNMlSwR1+vLlVDciOqFapDSbj+YOVOawR0R1aqlSKpZkt33DuOBPx9qe6CVnIi7Z+Px/KqM+OLCzlLY/RS+LbxQpDWcfTVRiP+S5qRTcE3M3UioN/e0BE/1+MpX90IGpvVkA63ILYbKEa4bM3ASL7ChTCr6xN5XT+GpVJveFKK1cfNx9ExHI4rzYE=
 
 [attachment]
-PATH = integrations/gitea-integration-sqlite/data/attachments
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/data/attachments
 
 [mailer]
 ENABLED     = true
 MAILER_TYPE = dummy
-FROM        = sqlite-integration-test@gitea.io
+FROM        = sqlite-{{TEST_TYPE}}-test@gitea.io
 
 [service]
 REGISTER_EMAIL_CONFIRM            = false
@@ -72,15 +72,15 @@ NO_REPLY_ADDRESS                  = noreply.example.org
 [picture]
 DISABLE_GRAVATAR              = false
 ENABLE_FEDERATED_AVATAR       = false
-AVATAR_UPLOAD_PATH            = integrations/gitea-integration-sqlite/data/avatars
-REPOSITORY_AVATAR_UPLOAD_PATH = integrations/gitea-integration-sqlite/data/repo-avatars
+AVATAR_UPLOAD_PATH            = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/data/avatars
+REPOSITORY_AVATAR_UPLOAD_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/data/repo-avatars
 
 [session]
 PROVIDER = file
-PROVIDER_CONFIG = integrations/gitea-integration-sqlite/data/sessions
+PROVIDER_CONFIG = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/data/sessions
 
 [log]
-MODE                 = test,file
+MODE                 = {{TEST_LOGGER}}
 ROOT_PATH            = {{REPO_TEST_DIR}}sqlite-log
 ROUTER               = ,
 XORM                 = file
@@ -103,7 +103,7 @@ INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTI3OTU5ODN9.O
 JWT_SECRET = KZb_QLUd4fYVyxetjxC4eZkrBgWM2SndOOWDNtgUUko
 
 [lfs]
-PATH = integrations/gitea-integration-sqlite/data/lfs
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/data/lfs
 
 [packages]
 ENABLED = true
diff --git a/tests/test_utils.go b/tests/test_utils.go
new file mode 100644
index 0000000000..0662530002
--- /dev/null
+++ b/tests/test_utils.go
@@ -0,0 +1,224 @@
+// Copyright 2017 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package tests
+
+import (
+	"context"
+	"database/sql"
+	"fmt"
+	"os"
+	"path"
+	"path/filepath"
+	"runtime"
+	"testing"
+
+	"code.gitea.io/gitea/models/unittest"
+	"code.gitea.io/gitea/modules/base"
+	"code.gitea.io/gitea/modules/git"
+	"code.gitea.io/gitea/modules/graceful"
+	"code.gitea.io/gitea/modules/log"
+	"code.gitea.io/gitea/modules/queue"
+	repo_module "code.gitea.io/gitea/modules/repository"
+	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/modules/storage"
+	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/routers"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func InitTest(requireGitea bool) {
+	giteaRoot := base.SetupGiteaRoot()
+	if giteaRoot == "" {
+		fmt.Println("Environment variable $GITEA_ROOT not set")
+		os.Exit(1)
+	}
+	if requireGitea {
+		giteaBinary := "gitea"
+		if runtime.GOOS == "windows" {
+			giteaBinary += ".exe"
+		}
+		setting.AppPath = path.Join(giteaRoot, giteaBinary)
+		if _, err := os.Stat(setting.AppPath); err != nil {
+			fmt.Printf("Could not find gitea binary at %s\n", setting.AppPath)
+			os.Exit(1)
+		}
+	}
+
+	giteaConf := os.Getenv("GITEA_CONF")
+	if giteaConf == "" {
+		fmt.Println("Environment variable $GITEA_CONF not set")
+		os.Exit(1)
+	} else if !path.IsAbs(giteaConf) {
+		setting.CustomConf = path.Join(giteaRoot, giteaConf)
+	} else {
+		setting.CustomConf = giteaConf
+	}
+
+	setting.SetCustomPathAndConf("", "", "")
+	setting.LoadForTest()
+	setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master"
+	_ = util.RemoveAll(repo_module.LocalCopyPath())
+
+	if err := git.InitFull(context.Background()); err != nil {
+		log.Fatal("git.InitOnceWithSync: %v", err)
+	}
+
+	setting.InitDBConfig()
+	if err := storage.Init(); err != nil {
+		fmt.Printf("Init storage failed: %v", err)
+		os.Exit(1)
+	}
+
+	switch {
+	case setting.Database.UseMySQL:
+		connType := "tcp"
+		if len(setting.Database.Host) > 0 && setting.Database.Host[0] == '/' { // looks like a unix socket
+			connType = "unix"
+		}
+
+		db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@%s(%s)/",
+			setting.Database.User, setting.Database.Passwd, connType, setting.Database.Host))
+		defer db.Close()
+		if err != nil {
+			log.Fatal("sql.Open: %v", err)
+		}
+		if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name)); err != nil {
+			log.Fatal("db.Exec: %v", err)
+		}
+	case setting.Database.UsePostgreSQL:
+		var db *sql.DB
+		var err error
+		if setting.Database.Host[0] == '/' {
+			db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@/%s?sslmode=%s&host=%s",
+				setting.Database.User, setting.Database.Passwd, setting.Database.Name, setting.Database.SSLMode, setting.Database.Host))
+		} else {
+			db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
+				setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
+		}
+
+		defer db.Close()
+		if err != nil {
+			log.Fatal("sql.Open: %v", err)
+		}
+		dbrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", setting.Database.Name))
+		if err != nil {
+			log.Fatal("db.Query: %v", err)
+		}
+		defer dbrows.Close()
+
+		if !dbrows.Next() {
+			if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", setting.Database.Name)); err != nil {
+				log.Fatal("db.Exec: CREATE DATABASE: %v", err)
+			}
+		}
+		// Check if we need to setup a specific schema
+		if len(setting.Database.Schema) == 0 {
+			break
+		}
+		db.Close()
+
+		if setting.Database.Host[0] == '/' {
+			db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@/%s?sslmode=%s&host=%s",
+				setting.Database.User, setting.Database.Passwd, setting.Database.Name, setting.Database.SSLMode, setting.Database.Host))
+		} else {
+			db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
+				setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
+		}
+		// This is a different db object; requires a different Close()
+		defer db.Close()
+		if err != nil {
+			log.Fatal("sql.Open: %v", err)
+		}
+		schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema))
+		if err != nil {
+			log.Fatal("db.Query: %v", err)
+		}
+		defer schrows.Close()
+
+		if !schrows.Next() {
+			// Create and setup a DB schema
+			if _, err = db.Exec(fmt.Sprintf("CREATE SCHEMA %s", setting.Database.Schema)); err != nil {
+				log.Fatal("db.Exec: CREATE SCHEMA: %v", err)
+			}
+		}
+
+	case setting.Database.UseMSSQL:
+		host, port := setting.ParseMSSQLHostPort(setting.Database.Host)
+		db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
+			host, port, "master", setting.Database.User, setting.Database.Passwd))
+		if err != nil {
+			log.Fatal("sql.Open: %v", err)
+		}
+		if _, err := db.Exec(fmt.Sprintf("If(db_id(N'%s') IS NULL) BEGIN CREATE DATABASE %s; END;", setting.Database.Name, setting.Database.Name)); err != nil {
+			log.Fatal("db.Exec: %v", err)
+		}
+		defer db.Close()
+	}
+
+	routers.GlobalInitInstalled(graceful.GetManager().HammerContext())
+}
+
+func PrepareTestEnv(t testing.TB, skip ...int) func() {
+	t.Helper()
+	ourSkip := 2
+	if len(skip) > 0 {
+		ourSkip += skip[0]
+	}
+	deferFn := PrintCurrentTest(t, ourSkip)
+	assert.NoError(t, unittest.LoadFixtures())
+	assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
+	assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath))
+	ownerDirs, err := os.ReadDir(setting.RepoRootPath)
+	if err != nil {
+		assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
+	}
+	for _, ownerDir := range ownerDirs {
+		if !ownerDir.Type().IsDir() {
+			continue
+		}
+		repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
+		if err != nil {
+			assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
+		}
+		for _, repoDir := range repoDirs {
+			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0o755)
+			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0o755)
+			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0o755)
+			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0o755)
+		}
+	}
+
+	return deferFn
+}
+
+// resetFixtures flushes queues, reloads fixtures and resets test repositories within a single test.
+// Most tests should call defer tests.PrepareTestEnv(t)() (or have onGiteaRun do that for them) but sometimes
+// within a single test this is required
+func ResetFixtures(t *testing.T) {
+	assert.NoError(t, queue.GetManager().FlushAll(context.Background(), -1))
+	assert.NoError(t, unittest.LoadFixtures())
+	assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
+	assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "tests/gitea-repositories-meta"), setting.RepoRootPath))
+	ownerDirs, err := os.ReadDir(setting.RepoRootPath)
+	if err != nil {
+		assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
+	}
+	for _, ownerDir := range ownerDirs {
+		if !ownerDir.Type().IsDir() {
+			continue
+		}
+		repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
+		if err != nil {
+			assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
+		}
+		for _, repoDir := range repoDirs {
+			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0o755)
+			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0o755)
+			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0o755)
+			_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0o755)
+		}
+	}
+}
diff --git a/integrations/testlogger.go b/tests/testlogger.go
similarity index 91%
rename from integrations/testlogger.go
rename to tests/testlogger.go
index 373ad80752..b65573a771 100644
--- a/integrations/testlogger.go
+++ b/tests/testlogger.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package integrations
+package tests
 
 import (
 	"context"
@@ -21,8 +21,8 @@ import (
 
 var (
 	prefix    string
-	slowTest  = 10 * time.Second
-	slowFlush = 5 * time.Second
+	SlowTest  = 10 * time.Second
+	SlowFlush = 5 * time.Second
 )
 
 // TestLogger is a logger which will write to the testing log
@@ -30,7 +30,7 @@ type TestLogger struct {
 	log.WriterLogger
 }
 
-var writerCloser = &testLoggerWriterCloser{}
+var WriterCloser = &testLoggerWriterCloser{}
 
 type testLoggerWriterCloser struct {
 	sync.RWMutex
@@ -119,21 +119,21 @@ func PrintCurrentTest(t testing.TB, skip ...int) func() {
 	} else {
 		fmt.Fprintf(os.Stdout, "=== %s (%s:%d)\n", t.Name(), strings.TrimPrefix(filename, prefix), line)
 	}
-	writerCloser.setT(&t)
+	WriterCloser.setT(&t)
 	return func() {
 		took := time.Since(start)
-		if took > slowTest {
+		if took > SlowTest {
 			if log.CanColorStdout {
 				fmt.Fprintf(os.Stdout, "+++ %s is a slow test (took %v)\n", fmt.Formatter(log.NewColoredValue(t.Name(), log.Bold, log.FgYellow)), fmt.Formatter(log.NewColoredValue(took, log.Bold, log.FgYellow)))
 			} else {
 				fmt.Fprintf(os.Stdout, "+++ %s is a slow test (took %v)\n", t.Name(), took)
 			}
 		}
-		timer := time.AfterFunc(slowFlush, func() {
+		timer := time.AfterFunc(SlowFlush, func() {
 			if log.CanColorStdout {
-				fmt.Fprintf(os.Stdout, "+++ %s ... still flushing after %v ...\n", fmt.Formatter(log.NewColoredValue(t.Name(), log.Bold, log.FgRed)), slowFlush)
+				fmt.Fprintf(os.Stdout, "+++ %s ... still flushing after %v ...\n", fmt.Formatter(log.NewColoredValue(t.Name(), log.Bold, log.FgRed)), SlowFlush)
 			} else {
-				fmt.Fprintf(os.Stdout, "+++ %s ... still flushing after %v ...\n", t.Name(), slowFlush)
+				fmt.Fprintf(os.Stdout, "+++ %s ... still flushing after %v ...\n", t.Name(), SlowFlush)
 			}
 		})
 		if err := queue.GetManager().FlushAll(context.Background(), 2*time.Minute); err != nil {
@@ -141,14 +141,14 @@ func PrintCurrentTest(t testing.TB, skip ...int) func() {
 		}
 		timer.Stop()
 		flushTook := time.Since(start) - took
-		if flushTook > slowFlush {
+		if flushTook > SlowFlush {
 			if log.CanColorStdout {
 				fmt.Fprintf(os.Stdout, "+++ %s had a slow clean-up flush (took %v)\n", fmt.Formatter(log.NewColoredValue(t.Name(), log.Bold, log.FgRed)), fmt.Formatter(log.NewColoredValue(flushTook, log.Bold, log.FgRed)))
 			} else {
 				fmt.Fprintf(os.Stdout, "+++ %s had a slow clean-up flush (took %v)\n", t.Name(), flushTook)
 			}
 		}
-		_ = writerCloser.Close()
+		_ = WriterCloser.Close()
 	}
 }
 
@@ -177,7 +177,7 @@ func (log *TestLogger) Init(config string) error {
 	if err != nil {
 		return err
 	}
-	log.NewWriterLogger(writerCloser)
+	log.NewWriterLogger(WriterCloser)
 	return nil
 }
 
@@ -203,5 +203,5 @@ func (log *TestLogger) GetName() string {
 func init() {
 	log.Register("test", NewTestLogger)
 	_, filename, _, _ := runtime.Caller(0)
-	prefix = strings.TrimSuffix(filename, "integrations/testlogger.go")
+	prefix = strings.TrimSuffix(filename, "tests/integration/testlogger.go")
 }