Skip to content
This repository has been archived by the owner on Jan 16, 2023. It is now read-only.

Set the test suite regardless of actual cloud connection. #218

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ repos:
- django-storages
- boto3
- google-cloud-storage
- moto
- repo: https://github.com/mgedmin/check-manifest
rev: "0.47"
hooks:
Expand Down
3 changes: 1 addition & 2 deletions collectfast/tests/command/test_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.test import override_settings as override_django_settings

from collectfast.management.commands.collectstatic import Command
from collectfast.tests.command.utils import call_collectstatic
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, let's restore this import.

from collectfast.tests.utils import clean_static_dir
from collectfast.tests.utils import create_static_file
from collectfast.tests.utils import live_test
Expand All @@ -13,8 +14,6 @@
from collectfast.tests.utils import override_storage_attr
from collectfast.tests.utils import test_many

from .utils import call_collectstatic

aws_backend_confs = {
"boto3": override_django_settings(
STATICFILES_STORAGE="storages.backends.s3boto3.S3Boto3Storage",
Expand Down
3 changes: 1 addition & 2 deletions collectfast/tests/command/test_disable.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@

from django.test import override_settings as override_django_settings

from collectfast.tests.command.utils import call_collectstatic
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem like a justified change, let's keep this a relative import.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the absolute path was more straightforward. But in this case, I guess relative is enough. 😄

from collectfast.tests.utils import clean_static_dir
from collectfast.tests.utils import create_static_file
from collectfast.tests.utils import live_test
from collectfast.tests.utils import make_test
from collectfast.tests.utils import override_setting

from .utils import call_collectstatic


@make_test
@override_django_settings(
Expand Down
10 changes: 6 additions & 4 deletions collectfast/tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@
AWS_PRELOAD_METADATA = True
AWS_STORAGE_BUCKET_NAME = "collectfast"
AWS_IS_GZIPPED = False
AWS_ACCESS_KEY_ID = os.environ.get("AWS_ACCESS_KEY_ID", "").strip()
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ACCESS_KEY", "").strip()
AWS_S3_REGION_NAME = "eu-central-1"
AWS_SECURITY_TOKEN = "testing"
AWS_SESSION_TOKEN = "testing"
AWS_ACCESS_KEY_ID = "testing"
AWS_SECRET_ACCESS_KEY = "testing"
AWS_S3_REGION_NAME = "ap-northeast-2"
AWS_S3_SIGNATURE_VERSION = "s3v4"
AWS_QUERYSTRING_AUTH = False
AWS_DEFAULT_ACL = None
S3_USE_SIGV4 = True
AWS_S3_HOST = "s3.eu-central-1.amazonaws.com"
AWS_S3_HOST = "s3.ap-northeast-2.amazonaws.com"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason to change this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, just for live testing with my accounts.
I'll revert it.


# Google Cloud
gcloud_credentials_json = os.environ.get("GCLOUD_CREDENTIALS", "").strip()
Expand Down
53 changes: 50 additions & 3 deletions collectfast/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
import os
import pathlib
import random
import unittest
import unittest.mock
import uuid
from typing import Any
from typing import Callable
from typing import Dict
from typing import Type
from typing import TypeVar
from typing import Union
from typing import cast

import boto3 # type: ignore
import moto # type: ignore
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's install types for boto3, and ignore moto in setup.cfg.

Related: pytest should be possible to remove from setup.cfg since it has gained typing support.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds great.

import pytest
from django.conf import settings as django_settings
from django.utils.module_loading import import_string
Expand All @@ -26,6 +30,11 @@
F = TypeVar("F", bound=Callable[..., Any])


class CloudTestCase(unittest.TestCase):
mock_s3: Any
gc: Any


def make_test(func: F) -> Type[unittest.TestCase]:
"""
Creates a class that inherits from `unittest.TestCase` with the decorated
Expand All @@ -36,7 +45,11 @@ def make_test(func: F) -> Type[unittest.TestCase]:
... def test_fn(case):
... case.assertEqual(fn(), 1337)
"""
case = type(func.__name__, (unittest.TestCase,), {func.__name__: func})
case = type(
func.__name__,
(unittest.TestCase,),
{func.__name__: func, "setUp": setUp, "tearDown": tearDown},
)
case.__module__ = func.__module__
return case

Expand All @@ -52,10 +65,12 @@ def test(func: F) -> Type[unittest.TestCase]:
... def test_fn(case):
... case.assertEqual(fn(), 1337)
"""
case_dict = {
case_dict: Dict[str, Union[F, Callable]] = {
"test_%s" % mutation_name: mutation(func)
for mutation_name, mutation in mutations.items()
}
case_dict["setUp"] = setUp
case_dict["tearDown"] = tearDown

case = type(func.__name__, (unittest.TestCase,), case_dict)
case.__module__ = func.__module__
Expand Down Expand Up @@ -109,3 +124,35 @@ def wrapper(*args, **kwargs):
return cast(F, wrapper)

return decorator


def create_bucket() -> None:
s3 = boto3.client("s3", region_name=django_settings.AWS_S3_REGION_NAME)
location = {"LocationConstraint": django_settings.AWS_S3_REGION_NAME}
s3.create_bucket(
Bucket=django_settings.AWS_STORAGE_BUCKET_NAME,
CreateBucketConfiguration=location,
)


def delete_bucket() -> None:
s3 = boto3.resource("s3", region_name=django_settings.AWS_S3_REGION_NAME)
bucket = s3.Bucket(django_settings.AWS_STORAGE_BUCKET_NAME)
bucket.objects.delete()
bucket.delete()


def setUp(case: CloudTestCase) -> None:
case.mock_s3 = moto.mock_s3()
case.mock_s3.start()
create_bucket()
case.gc = unittest.mock.patch("storages.backends.gcloud.GoogleCloudStorage")
mock_gcs = case.gc.start().return_value
mock_gcs._bucket = unittest.mock.MagicMock()
mock_gcs.bucket.get_blob.return_value = None


def tearDown(case: CloudTestCase) -> None:
delete_bucket()
case.mock_s3.stop()
case.gc.stop()
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ boto3
google-cloud-storage
pytest
pytest-django
moto[s3]