diff --git a/api/integrations/amplitude/tests/test_views.py b/api/integrations/amplitude/tests/test_views.py deleted file mode 100644 index 1b0524386192..000000000000 --- a/api/integrations/amplitude/tests/test_views.py +++ /dev/null @@ -1,130 +0,0 @@ -import json -from unittest.case import TestCase - -import pytest -from django.urls import reverse -from rest_framework import status -from rest_framework.test import APIClient - -from environments.models import Environment -from integrations.amplitude.models import AmplitudeConfiguration -from organisations.models import Organisation, OrganisationRole -from projects.models import Project -from util.tests import Helper - - -@pytest.mark.django_db -class AmplitudeConfigurationTestCase(TestCase): - def setUp(self): - self.client = APIClient() - user = Helper.create_ffadminuser() - self.client.force_authenticate(user=user) - - self.organisation = Organisation.objects.create(name="Test Org") - user.add_organisation( - self.organisation, OrganisationRole.ADMIN - ) # admin to bypass perms - - self.project = Project.objects.create( - name="Test project", organisation=self.organisation - ) - self.environment = Environment.objects.create( - name="Test Environment", project=self.project - ) - self.list_url = reverse( - "api-v1:environments:integrations-amplitude-list", - args=[self.environment.api_key], - ) - - def test_should_create_amplitude_config_when_post(self): - # Given - data = {"api_key": "abc-123"} - - # When - response = self.client.post( - self.list_url, - data=json.dumps(data), - content_type="application/json", - ) - - # Then - assert response.status_code == status.HTTP_201_CREATED - assert ( - AmplitudeConfiguration.objects.filter(environment=self.environment).count() - == 1 - ) - - def test_should_return_BadRequest_when_duplicate_amplitude_config_is_posted(self): - # Given - config = AmplitudeConfiguration.objects.create( - api_key="api_123", environment=self.environment - ) - - # When - data = {"api_key": config.api_key} - response = self.client.post( - self.list_url, - data=json.dumps(data), - content_type="application/json", - ) - - # Then - assert response.status_code == status.HTTP_400_BAD_REQUEST - assert ( - AmplitudeConfiguration.objects.filter(environment=self.environment).count() - == 1 - ) - - def test_should_update_configuration_when_put(self): - # Given - config = AmplitudeConfiguration.objects.create( - api_key="api_123", environment=self.environment - ) - - api_key_updated = "new api" - data = {"api_key": api_key_updated} - - # When - url = reverse( - "api-v1:environments:integrations-amplitude-detail", - args=[self.environment.api_key, config.id], - ) - response = self.client.put( - url, - data=json.dumps(data), - content_type="application/json", - ) - config.refresh_from_db() - - # Then - assert response.status_code == status.HTTP_200_OK - assert config.api_key == api_key_updated - - def test_should_return_amplitude_config_list_when_requested(self): - # Given - set up data - - # When - response = self.client.get(self.list_url) - - # Then - assert response.status_code == status.HTTP_200_OK - - def test_should_remove_configuration_when_delete(self): - # Given - config = AmplitudeConfiguration.objects.create( - api_key="api_123", environment=self.environment - ) - - # When - url = reverse( - "api-v1:environments:integrations-amplitude-detail", - args=[self.environment.api_key, config.id], - ) - res = self.client.delete(url) - - # Then - assert res.status_code == status.HTTP_204_NO_CONTENT - # and - assert not AmplitudeConfiguration.objects.filter( - environment=self.environment - ).exists() diff --git a/api/integrations/datadog/tests/__init__.py b/api/integrations/datadog/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/integrations/datadog/tests/test_views.py b/api/integrations/datadog/tests/test_views.py deleted file mode 100644 index 7fe00bb12e69..000000000000 --- a/api/integrations/datadog/tests/test_views.py +++ /dev/null @@ -1,121 +0,0 @@ -import json -from unittest.case import TestCase - -import pytest -from django.urls import reverse -from rest_framework import status -from rest_framework.test import APIClient - -from environments.models import Environment -from integrations.datadog.models import DataDogConfiguration -from organisations.models import Organisation, OrganisationRole -from projects.models import Project -from util.tests import Helper - - -@pytest.mark.django_db -class DatadogConfigurationTestCase(TestCase): - def setUp(self): - self.client = APIClient() - user = Helper.create_ffadminuser() - self.client.force_authenticate(user=user) - - self.organisation = Organisation.objects.create(name="Test Org") - user.add_organisation( - self.organisation, OrganisationRole.ADMIN - ) # admin to bypass perms - - self.project = Project.objects.create( - name="Test project", organisation=self.organisation - ) - self.environment = Environment.objects.create( - name="Test Environment", project=self.project - ) - self.list_url = reverse( - "api-v1:projects:integrations-datadog-list", args=[self.project.id] - ) - - def test_should_create_datadog_config_when_post(self): - # Given setup data - data = {"base_url": "http://test.com", "api_key": "abc-123"} - - # When - response = self.client.post( - self.list_url, - data=json.dumps(data), - content_type="application/json", - ) - - # Then - assert response.status_code == status.HTTP_201_CREATED - # and - assert DataDogConfiguration.objects.filter(project=self.project).count() == 1 - - def test_should_return_BadRequest_when_duplicate_datadog_config_is_posted(self): - # Given - DataDogConfiguration.objects.create( - base_url="http://test.com", api_key="api_123", project=self.project - ) - data = {"base_url": "http://test.com", "api_key": "abc-123"} - - # When - response = self.client.post( - self.list_url, - data=json.dumps(data), - content_type="application/json", - ) - - # Then - assert response.status_code == status.HTTP_400_BAD_REQUEST - assert DataDogConfiguration.objects.filter(project=self.project).count() == 1 - - # - def test_should_update_configuration_when_put(self): - # Given - config = DataDogConfiguration.objects.create( - base_url="http://test.com", api_key="api_123", project=self.project - ) - api_key_updated = "new api" - data = {"base_url": config.base_url, "api_key": api_key_updated} - - # When - url = reverse( - "api-v1:projects:integrations-datadog-detail", - args=[self.project.id, config.id], - ) - response = self.client.put( - url, - data=json.dumps(data), - content_type="application/json", - ) - config.refresh_from_db() - - # Then - assert response.status_code == status.HTTP_200_OK - assert config.api_key == api_key_updated - - def test_should_return_datadog_config_list_when_requested(self): - # Given - set up data - - # When - response = self.client.get(self.list_url) - - # Then - assert response.status_code == status.HTTP_200_OK - - def test_should_remove_configuration_when_delete(self): - # Given - config = DataDogConfiguration.objects.create( - base_url="http://test.com", api_key="api_123", project=self.project - ) - # When - url = reverse( - "api-v1:projects:integrations-datadog-detail", - args=[self.project.id, config.id], - ) - res = self.client.delete(url) - - # Then - assert res.status_code == status.HTTP_204_NO_CONTENT - # and - assert not DataDogConfiguration.objects.filter(project=self.project).exists() diff --git a/api/integrations/dynatrace/tests/__init__.py b/api/integrations/dynatrace/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/integrations/heap/tests/__init__.py b/api/integrations/heap/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/integrations/mixpanel/tests/__init__.py b/api/integrations/mixpanel/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/integrations/new_relic/tests/__init__.py b/api/integrations/new_relic/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/integrations/opencensus/tests/__init__.py b/api/integrations/opencensus/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/integrations/rudderstack/tests/__init__.py b/api/integrations/rudderstack/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/integrations/segment/tests/__init__.py b/api/integrations/segment/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/integrations/webhook/tests/__init__.py b/api/integrations/webhook/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/projects/tags/tests/__init__.py b/api/projects/tags/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/projects/tests/__init__.py b/api/projects/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/projects/tests/conftest.py b/api/projects/tests/conftest.py deleted file mode 100644 index 303298a0f931..000000000000 --- a/api/projects/tests/conftest.py +++ /dev/null @@ -1,13 +0,0 @@ -import pytest - -from segments.models import Segment - - -@pytest.fixture() -def segments(project): - segments = [] - for i in range(3): - segments.append( - Segment.objects.create(name=f"Test Segment {i}", project=project) - ) - return segments diff --git a/api/segments/tests/test_models.py b/api/segments/tests/test_models.py deleted file mode 100644 index 7c49ad1e263e..000000000000 --- a/api/segments/tests/test_models.py +++ /dev/null @@ -1,46 +0,0 @@ -from unittest import TestCase - -import pytest - -from environments.identities.models import Identity -from environments.models import Environment -from organisations.models import Organisation -from projects.models import Project -from segments.models import PERCENTAGE_SPLIT, Condition, Segment, SegmentRule - - -@pytest.mark.django_db -class SegmentRuleTest(TestCase): - def setUp(self) -> None: - self.organisation = Organisation.objects.create(name="Test Org") - self.project = Project.objects.create( - name="Test Project", organisation=self.organisation - ) - self.environment = Environment.objects.create( - name="Test Environment", project=self.project - ) - self.identity = Identity.objects.create( - environment=self.environment, identifier="test_identity" - ) - self.segment = Segment.objects.create(project=self.project, name="test_segment") - - def test_get_segment_returns_parent_segment_for_nested_rule(self): - # Given - parent_rule = SegmentRule.objects.create( - segment=self.segment, type=SegmentRule.ALL_RULE - ) - child_rule = SegmentRule.objects.create( - rule=parent_rule, type=SegmentRule.ALL_RULE - ) - grandchild_rule = SegmentRule.objects.create( - rule=child_rule, type=SegmentRule.ALL_RULE - ) - Condition.objects.create( - operator=PERCENTAGE_SPLIT, value=0.1, rule=grandchild_rule - ) - - # When - segment = grandchild_rule.get_segment() - - # Then - assert segment == self.segment diff --git a/api/tests/unit/integrations/amplitude/test_unit_amplitude_views.py b/api/tests/unit/integrations/amplitude/test_unit_amplitude_views.py index 82a0349594a4..52b9d16982bf 100644 --- a/api/tests/unit/integrations/amplitude/test_unit_amplitude_views.py +++ b/api/tests/unit/integrations/amplitude/test_unit_amplitude_views.py @@ -1,7 +1,133 @@ import json +from unittest.case import TestCase +import pytest from django.urls import reverse from rest_framework import status +from rest_framework.test import APIClient + +from environments.models import Environment +from integrations.amplitude.models import AmplitudeConfiguration +from organisations.models import Organisation, OrganisationRole +from projects.models import Project +from util.tests import Helper + + +@pytest.mark.django_db +class AmplitudeConfigurationTestCase(TestCase): + def setUp(self): + self.client = APIClient() + user = Helper.create_ffadminuser() + self.client.force_authenticate(user=user) + + self.organisation = Organisation.objects.create(name="Test Org") + user.add_organisation( + self.organisation, OrganisationRole.ADMIN + ) # admin to bypass perms + + self.project = Project.objects.create( + name="Test project", organisation=self.organisation + ) + self.environment = Environment.objects.create( + name="Test Environment", project=self.project + ) + self.list_url = reverse( + "api-v1:environments:integrations-amplitude-list", + args=[self.environment.api_key], + ) + + def test_should_create_amplitude_config_when_post(self): + # Given + data = {"api_key": "abc-123"} + + # When + response = self.client.post( + self.list_url, + data=json.dumps(data), + content_type="application/json", + ) + + # Then + assert response.status_code == status.HTTP_201_CREATED + assert ( + AmplitudeConfiguration.objects.filter(environment=self.environment).count() + == 1 + ) + + def test_should_return_BadRequest_when_duplicate_amplitude_config_is_posted(self): + # Given + config = AmplitudeConfiguration.objects.create( + api_key="api_123", environment=self.environment + ) + + # When + data = {"api_key": config.api_key} + response = self.client.post( + self.list_url, + data=json.dumps(data), + content_type="application/json", + ) + + # Then + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert ( + AmplitudeConfiguration.objects.filter(environment=self.environment).count() + == 1 + ) + + def test_should_update_configuration_when_put(self): + # Given + config = AmplitudeConfiguration.objects.create( + api_key="api_123", environment=self.environment + ) + + api_key_updated = "new api" + data = {"api_key": api_key_updated} + + # When + url = reverse( + "api-v1:environments:integrations-amplitude-detail", + args=[self.environment.api_key, config.id], + ) + response = self.client.put( + url, + data=json.dumps(data), + content_type="application/json", + ) + config.refresh_from_db() + + # Then + assert response.status_code == status.HTTP_200_OK + assert config.api_key == api_key_updated + + def test_should_return_amplitude_config_list_when_requested(self): + # Given - set up data + + # When + response = self.client.get(self.list_url) + + # Then + assert response.status_code == status.HTTP_200_OK + + def test_should_remove_configuration_when_delete(self): + # Given + config = AmplitudeConfiguration.objects.create( + api_key="api_123", environment=self.environment + ) + + # When + url = reverse( + "api-v1:environments:integrations-amplitude-detail", + args=[self.environment.api_key, config.id], + ) + res = self.client.delete(url) + + # Then + assert res.status_code == status.HTTP_204_NO_CONTENT + # and + assert not AmplitudeConfiguration.objects.filter( + environment=self.environment + ).exists() def test_create_amplitude_integration(environment, admin_client): diff --git a/api/integrations/datadog/tests/test_datadog.py b/api/tests/unit/integrations/datadog/test_unit_datadog.py similarity index 100% rename from api/integrations/datadog/tests/test_datadog.py rename to api/tests/unit/integrations/datadog/test_unit_datadog.py diff --git a/api/tests/unit/integrations/datadog/test_unit_datadog_views.py b/api/tests/unit/integrations/datadog/test_unit_datadog_views.py index d9ed855a80bf..fe7dd124f5ff 100644 --- a/api/tests/unit/integrations/datadog/test_unit_datadog_views.py +++ b/api/tests/unit/integrations/datadog/test_unit_datadog_views.py @@ -1,7 +1,124 @@ import json +from unittest.case import TestCase +import pytest from django.urls import reverse from rest_framework import status +from rest_framework.test import APIClient + +from environments.models import Environment +from integrations.datadog.models import DataDogConfiguration +from organisations.models import Organisation, OrganisationRole +from projects.models import Project +from util.tests import Helper + + +@pytest.mark.django_db +class DatadogConfigurationTestCase(TestCase): + def setUp(self): + self.client = APIClient() + user = Helper.create_ffadminuser() + self.client.force_authenticate(user=user) + + self.organisation = Organisation.objects.create(name="Test Org") + user.add_organisation( + self.organisation, OrganisationRole.ADMIN + ) # admin to bypass perms + + self.project = Project.objects.create( + name="Test project", organisation=self.organisation + ) + self.environment = Environment.objects.create( + name="Test Environment", project=self.project + ) + self.list_url = reverse( + "api-v1:projects:integrations-datadog-list", args=[self.project.id] + ) + + def test_should_create_datadog_config_when_post(self): + # Given setup data + data = {"base_url": "http://test.com", "api_key": "abc-123"} + + # When + response = self.client.post( + self.list_url, + data=json.dumps(data), + content_type="application/json", + ) + + # Then + assert response.status_code == status.HTTP_201_CREATED + # and + assert DataDogConfiguration.objects.filter(project=self.project).count() == 1 + + def test_should_return_BadRequest_when_duplicate_datadog_config_is_posted(self): + # Given + DataDogConfiguration.objects.create( + base_url="http://test.com", api_key="api_123", project=self.project + ) + data = {"base_url": "http://test.com", "api_key": "abc-123"} + + # When + response = self.client.post( + self.list_url, + data=json.dumps(data), + content_type="application/json", + ) + + # Then + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert DataDogConfiguration.objects.filter(project=self.project).count() == 1 + + # + def test_should_update_configuration_when_put(self): + # Given + config = DataDogConfiguration.objects.create( + base_url="http://test.com", api_key="api_123", project=self.project + ) + api_key_updated = "new api" + data = {"base_url": config.base_url, "api_key": api_key_updated} + + # When + url = reverse( + "api-v1:projects:integrations-datadog-detail", + args=[self.project.id, config.id], + ) + response = self.client.put( + url, + data=json.dumps(data), + content_type="application/json", + ) + config.refresh_from_db() + + # Then + assert response.status_code == status.HTTP_200_OK + assert config.api_key == api_key_updated + + def test_should_return_datadog_config_list_when_requested(self): + # Given - set up data + + # When + response = self.client.get(self.list_url) + + # Then + assert response.status_code == status.HTTP_200_OK + + def test_should_remove_configuration_when_delete(self): + # Given + config = DataDogConfiguration.objects.create( + base_url="http://test.com", api_key="api_123", project=self.project + ) + # When + url = reverse( + "api-v1:projects:integrations-datadog-detail", + args=[self.project.id, config.id], + ) + res = self.client.delete(url) + + # Then + assert res.status_code == status.HTTP_204_NO_CONTENT + # and + assert not DataDogConfiguration.objects.filter(project=self.project).exists() def test_create_datadog_configuration_in_project_with_deleted_configuration( diff --git a/api/integrations/dynatrace/tests/test_dynatrace.py b/api/tests/unit/integrations/dynatrace/test_unit_dynatrace.py similarity index 100% rename from api/integrations/dynatrace/tests/test_dynatrace.py rename to api/tests/unit/integrations/dynatrace/test_unit_dynatrace.py diff --git a/api/integrations/dynatrace/tests/test_views.py b/api/tests/unit/integrations/dynatrace/test_unit_dynatrace_views.py similarity index 100% rename from api/integrations/dynatrace/tests/test_views.py rename to api/tests/unit/integrations/dynatrace/test_unit_dynatrace_views.py diff --git a/api/integrations/heap/tests/test_views.py b/api/tests/unit/integrations/heap/test_unit_heap_views.py similarity index 100% rename from api/integrations/heap/tests/test_views.py rename to api/tests/unit/integrations/heap/test_unit_heap_views.py diff --git a/api/integrations/mixpanel/tests/test_views.py b/api/tests/unit/integrations/mixpanel/test_unit_mixpanel_views.py similarity index 100% rename from api/integrations/mixpanel/tests/test_views.py rename to api/tests/unit/integrations/mixpanel/test_unit_mixpanel_views.py diff --git a/api/integrations/amplitude/tests/__init__.py b/api/tests/unit/integrations/new_relic/__init__.py similarity index 100% rename from api/integrations/amplitude/tests/__init__.py rename to api/tests/unit/integrations/new_relic/__init__.py diff --git a/api/tests/unit/integrations/newrelic/conftest.py b/api/tests/unit/integrations/new_relic/conftest.py similarity index 100% rename from api/tests/unit/integrations/newrelic/conftest.py rename to api/tests/unit/integrations/new_relic/conftest.py diff --git a/api/integrations/new_relic/tests/test_new_relic.py b/api/tests/unit/integrations/new_relic/test_unit_new_relic.py similarity index 100% rename from api/integrations/new_relic/tests/test_new_relic.py rename to api/tests/unit/integrations/new_relic/test_unit_new_relic.py diff --git a/api/integrations/new_relic/tests/test_views.py b/api/tests/unit/integrations/new_relic/test_unit_new_relic_views.py similarity index 85% rename from api/integrations/new_relic/tests/test_views.py rename to api/tests/unit/integrations/new_relic/test_unit_new_relic_views.py index 54512feeb25f..f2ee03f4c63f 100644 --- a/api/integrations/new_relic/tests/test_views.py +++ b/api/tests/unit/integrations/new_relic/test_unit_new_relic_views.py @@ -143,3 +143,27 @@ def test_should_remove_configuration_when_delete(self): assert res.status_code == status.HTTP_204_NO_CONTENT # and assert not NewRelicConfiguration.objects.filter(project=self.project).exists() + + +def test_create_newrelic_configuration_in_project_with_deleted_configuration( + admin_client, project, deleted_newrelic_configuration +): + # Given + url = reverse("api-v1:projects:integrations-new-relic-list", args=[project.id]) + + api_key, base_url, app_id = "some-key", "https://api.newrelic.com/", "1" + + # When + response = admin_client.post( + path=url, + data=json.dumps({"api_key": api_key, "base_url": base_url, "app_id": app_id}), + content_type="application/json", + ) + + # Then + assert response.status_code == status.HTTP_201_CREATED + + response_json = response.json() + assert response_json["api_key"] == api_key + assert response_json["base_url"] == base_url + assert response_json["app_id"] == app_id diff --git a/api/tests/unit/integrations/newrelic/__init__.py b/api/tests/unit/integrations/newrelic/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/api/tests/unit/integrations/newrelic/test_unit_newrelic_views.py b/api/tests/unit/integrations/newrelic/test_unit_newrelic_views.py deleted file mode 100644 index 199431d8fdc6..000000000000 --- a/api/tests/unit/integrations/newrelic/test_unit_newrelic_views.py +++ /dev/null @@ -1,28 +0,0 @@ -import json - -from django.urls import reverse -from rest_framework import status - - -def test_create_newrelic_configuration_in_project_with_deleted_configuration( - admin_client, project, deleted_newrelic_configuration -): - # Given - url = reverse("api-v1:projects:integrations-new-relic-list", args=[project.id]) - - api_key, base_url, app_id = "some-key", "https://api.newrelic.com/", "1" - - # When - response = admin_client.post( - path=url, - data=json.dumps({"api_key": api_key, "base_url": base_url, "app_id": app_id}), - content_type="application/json", - ) - - # Then - assert response.status_code == status.HTTP_201_CREATED - - response_json = response.json() - assert response_json["api_key"] == api_key - assert response_json["base_url"] == base_url - assert response_json["app_id"] == app_id diff --git a/api/integrations/opencensus/tests/test_middleware.py b/api/tests/unit/integrations/opencensus/test_unit_opencensus_middleware.py similarity index 100% rename from api/integrations/opencensus/tests/test_middleware.py rename to api/tests/unit/integrations/opencensus/test_unit_opencensus_middleware.py diff --git a/api/integrations/opencensus/tests/test_querylogger.py b/api/tests/unit/integrations/opencensus/test_unit_opencensus_querylogger.py similarity index 100% rename from api/integrations/opencensus/tests/test_querylogger.py rename to api/tests/unit/integrations/opencensus/test_unit_opencensus_querylogger.py diff --git a/api/integrations/rudderstack/tests/test_rudderstack.py b/api/tests/unit/integrations/rudderstack/test_unit_rudderstack.py similarity index 100% rename from api/integrations/rudderstack/tests/test_rudderstack.py rename to api/tests/unit/integrations/rudderstack/test_unit_rudderstack.py diff --git a/api/integrations/rudderstack/tests/test_views.py b/api/tests/unit/integrations/rudderstack/test_unit_rudderstack_views.py similarity index 100% rename from api/integrations/rudderstack/tests/test_views.py rename to api/tests/unit/integrations/rudderstack/test_unit_rudderstack_views.py diff --git a/api/integrations/segment/tests/test_views.py b/api/tests/unit/integrations/segment/test_unit_segment_views.py similarity index 100% rename from api/integrations/segment/tests/test_views.py rename to api/tests/unit/integrations/segment/test_unit_segment_views.py diff --git a/api/integrations/sentry/tests/test_middleware.py b/api/tests/unit/integrations/sentry/test_unit_sentry_middleware.py similarity index 100% rename from api/integrations/sentry/tests/test_middleware.py rename to api/tests/unit/integrations/sentry/test_unit_sentry_middleware.py diff --git a/api/integrations/sentry/tests/test_sampler.py b/api/tests/unit/integrations/sentry/test_unit_sentry_sampler.py similarity index 100% rename from api/integrations/sentry/tests/test_sampler.py rename to api/tests/unit/integrations/sentry/test_unit_sentry_sampler.py diff --git a/api/integrations/slack/tests/test_authentication.py b/api/tests/unit/integrations/slack/test_unit_slack_authentication.py similarity index 100% rename from api/integrations/slack/tests/test_authentication.py rename to api/tests/unit/integrations/slack/test_unit_slack_authentication.py diff --git a/api/integrations/slack/tests/test_permissions.py b/api/tests/unit/integrations/slack/test_unit_slack_permissions.py similarity index 100% rename from api/integrations/slack/tests/test_permissions.py rename to api/tests/unit/integrations/slack/test_unit_slack_permissions.py diff --git a/api/integrations/webhook/tests/test_serializer.py b/api/tests/unit/integrations/webhook/test_unit_webhook_serializers.py similarity index 100% rename from api/integrations/webhook/tests/test_serializer.py rename to api/tests/unit/integrations/webhook/test_unit_webhook_serializers.py diff --git a/api/integrations/webhook/tests/test_views.py b/api/tests/unit/integrations/webhook/test_unit_webhook_views.py similarity index 100% rename from api/integrations/webhook/tests/test_views.py rename to api/tests/unit/integrations/webhook/test_unit_webhook_views.py diff --git a/api/projects/tags/tests/test_models.py b/api/tests/unit/projects/tags/test_unit_projects_tags_models.py similarity index 100% rename from api/projects/tags/tests/test_models.py rename to api/tests/unit/projects/tags/test_unit_projects_tags_models.py diff --git a/api/projects/tags/tests/test_permissions.py b/api/tests/unit/projects/tags/test_unit_projects_tags_permissions.py similarity index 100% rename from api/projects/tags/tests/test_permissions.py rename to api/tests/unit/projects/tags/test_unit_projects_tags_permissions.py