Skip to content

Commit

Permalink
test: improve integration testing
Browse files Browse the repository at this point in the history
  • Loading branch information
lengau committed Apr 12, 2023
2 parents d643e70 + a7fe0b7 commit aaa5568
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 53 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install python packages and dependencies
Expand Down Expand Up @@ -44,17 +44,17 @@ jobs:
tests:
strategy:
matrix:
os: [macos-12, ubuntu-18.04, ubuntu-20.04, windows-2019]
os: [macos-12, ubuntu-20.04, ubuntu-22.04, windows-2019]
python-version: ["3.8", "3.9", "3.10"]

runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }} on ${{ matrix.os }}
uses: actions/setup-python@v2
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand Down
3 changes: 2 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ include_package_data = True
packages = find:
zip_safe = False
install_requires =
pydantic
pydantic>=1.10
keyring>=23.0
macaroonbakery
overrides
Expand Down Expand Up @@ -63,6 +63,7 @@ test =
pytest-check
pytest-mock
pytest-subprocess
pytest-timeout>=2.0
tox
types-requests
types-setuptools
Expand Down
35 changes: 32 additions & 3 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import os
import shutil
import uuid
from pathlib import Path

import pytest
Expand All @@ -37,7 +38,17 @@ def charm_client():


@pytest.fixture
def fake_charm_file(tmpdir):
def charmhub_charm_name():
"""Allow overriding the user to override the test charm.
NOTE: Most integration tests check specifics about craft-store-test-charm,
so overriding the test charm may cause test failures.
"""
yield os.getenv("CRAFT_STORE_TEST_CHARM", default="craft-store-test-charm")


@pytest.fixture
def fake_charm_file(tmpdir, charmhub_charm_name):
"""Provide a fake charm to upload to charmhub."""
# Make tmpdir Path instead of Path-like.
prime_dir = Path(tmpdir) / "prime"
Expand All @@ -47,7 +58,7 @@ def fake_charm_file(tmpdir):
with medadata_path.open("w") as metadata_file:
yaml.safe_dump(
data={
"name": "craft-store-test-charm",
"name": charmhub_charm_name,
"display-name": "display",
"description": "description",
"summary": "summary",
Expand Down Expand Up @@ -90,3 +101,21 @@ def fake_charm_file(tmpdir):
)

return charm_file


@pytest.fixture
def unregistered_charm_name(charm_client):
"""Get an unregistered name for use in tests"""
account_id = charm_client.whoami().get("account", {}).get("id", "").lower()
registered_names = {result.name for result in charm_client.list_registered_names()}
while (name := f"test-{account_id}-{uuid.uuid4()}") in registered_names:
# Regenerate UUIDs until we find one that's not registered or timeout.
pass
yield name


def needs_charmhub_credentials():
return pytest.mark.skipif(
not os.getenv("CRAFT_STORE_CHARMCRAFT_CREDENTIALS"),
reason="CRAFT_STORE_CHARMCRAFT_CREDENTIALS are not set",
)
2 changes: 2 additions & 0 deletions tests/integration/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
from craft_store import errors
from craft_store.auth import Auth, MemoryKeyring

pytestmark = pytest.mark.timeout(10) # Timeout if any test takes over 10 sec.


@pytest.fixture
def test_keyring():
Expand Down
14 changes: 7 additions & 7 deletions tests/integration/test_get_list_releases.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@


import datetime
import os
from typing import cast

import pytest

from craft_store.models import charm_list_releases_model

from .conftest import needs_charmhub_credentials

@pytest.mark.skipif(
not os.getenv("CRAFT_STORE_CHARMCRAFT_CREDENTIALS"),
reason="CRAFT_STORE_CHARMCRAFT_CREDENTIALS are not set",
)
def test_charm_get_list_releases(charm_client):
pytestmark = pytest.mark.timeout(10) # Timeout if any test takes over 10 sec.


@needs_charmhub_credentials()
def test_charm_get_list_releases(charm_client, charmhub_charm_name):
model = cast(
charm_list_releases_model.ListReleasesModel,
charm_client.get_list_releases(name="craft-store-test-charm"),
charm_client.get_list_releases(name=charmhub_charm_name),
)

assert len(model.channel_map) == 1
Expand Down
45 changes: 25 additions & 20 deletions tests/integration/test_register_unregister.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,37 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import pytest

import datetime
import os
from craft_store.errors import StoreServerError

import pytest
from .conftest import needs_charmhub_credentials

pytestmark = pytest.mark.timeout(10) # Timeout if any test takes over 10 sec.


@pytest.mark.skipif(
not os.getenv("CRAFT_STORE_CHARMCRAFT_CREDENTIALS"),
reason="CRAFT_STORE_CHARMCRAFT_CREDENTIALS are not set",
)
def test_register_unregister_cycle(charm_client):
whoami = charm_client.whoami()
account_id = whoami.get("account", {}).get("id")
timestamp_us = int(datetime.datetime.utcnow().timestamp() * 1_000_000)
charm_name = f"test-charm-{account_id}-{timestamp_us}"
@needs_charmhub_credentials()
@pytest.mark.parametrize("entity_type", ["charm", "bundle"])
def test_register_unregister_cycle(charm_client, unregistered_charm_name, entity_type):
try:
charm_client.register_name(unregistered_charm_name, entity_type=entity_type)

names = [result.name for result in charm_client.list_registered_names()]
assert charm_name not in names, "Charm name already registered, test setup failed."
names = {result.name for result in charm_client.list_registered_names()}
assert (
unregistered_charm_name in names
), f"{entity_type} was not successfully registered."
finally:
charm_client.unregister_name(unregistered_charm_name)

charm_client.register_name(charm_name, entity_type="charm")
names = {result.name for result in charm_client.list_registered_names()}
assert (
unregistered_charm_name not in names
), f"{entity_type} was not successfully unregistered."

names = [result.name for result in charm_client.list_registered_names()]
assert charm_name not in names, "Charm was not successfully registered."

charm_client.unregister_package(charm_name)
@needs_charmhub_credentials()
def test_unregister_nonexistent(charm_client, unregistered_charm_name):
with pytest.raises(StoreServerError) as exc_info:
charm_client.unregister_name(unregistered_charm_name)

names = [result.name for result in charm_client.list_registered_names()]
assert charm_name not in names, "Charm was not successfully unregistered."
assert "resource-not-found" in exc_info.value.error_list
17 changes: 7 additions & 10 deletions tests/integration/test_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,22 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.


import os

import pytest

from craft_store.models import release_request_model

from .conftest import needs_charmhub_credentials

pytestmark = pytest.mark.timeout(10) # Timeout if any test takes over 10 sec.


@pytest.mark.skipif(
not os.getenv("CRAFT_STORE_CHARMCRAFT_CREDENTIALS"),
reason="CRAFT_STORE_CHARMCRAFT_CREDENTIALS are not set",
)
def test_charm_release(charm_client):
@needs_charmhub_credentials()
def test_charm_release(charm_client, charmhub_charm_name):
model = release_request_model.ReleaseRequestModel(
channel="edge", revision=1, resources=[]
)

charm_client.release(
name="craft-store-test-charm",
name=charmhub_charm_name,
release_request=[model],
)
16 changes: 8 additions & 8 deletions tests/integration/test_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,32 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.


import os
from typing import cast

import pytest

from craft_store.models import revisions_model

from .conftest import needs_charmhub_credentials

@pytest.mark.skipif(
not os.getenv("CRAFT_STORE_CHARMCRAFT_CREDENTIALS"),
reason="CRAFT_STORE_CHARMCRAFT_CREDENTIALS are not set",
)
def test_charm_upload(charm_client, fake_charm_file):
pytestmark = pytest.mark.timeout(10) # Timeout if any test takes over 10 sec.


@needs_charmhub_credentials()
def test_charm_upload(charm_client, fake_charm_file, charmhub_charm_name):
upload_id = charm_client.upload_file(filepath=fake_charm_file)

request_model = revisions_model.RevisionsRequestModel(**{"upload-id": upload_id})

model_response = cast(
revisions_model.RevisionsResponseModel,
charm_client.notify_revision(
name="craft-store-test-charm",
name=charmhub_charm_name,
revision_request=request_model,
),
)

assert (
model_response.status_url
== f"/v1/charm/craft-store-test-charm/revisions/review?upload-id={upload_id}"
== f"/v1/charm/{charmhub_charm_name}/revisions/review?upload-id={upload_id}"
)

0 comments on commit aaa5568

Please sign in to comment.