diff --git a/reconcile/test/glitchtip/conftest.py b/reconcile/test/glitchtip/conftest.py index 9274b95c0..9738895a3 100644 --- a/reconcile/test/glitchtip/conftest.py +++ b/reconcile/test/glitchtip/conftest.py @@ -18,26 +18,29 @@ def glitchtip_token() -> str: @pytest.fixture -def glitchtip_client_minimal(glitchtip_url, glitchtip_token) -> GlitchtipClient: +def glitchtip_client_minimal( + glitchtip_url: str, glitchtip_token: str +) -> GlitchtipClient: return GlitchtipClient(host=glitchtip_url, token=glitchtip_token) @pytest.fixture def glitchtip_client( - glitchtip_client_minimal, glitchtip_server_full_api_response + glitchtip_client_minimal: GlitchtipClient, + glitchtip_server_full_api_response: None, ) -> GlitchtipClient: return glitchtip_client_minimal @pytest.fixture -def fx(): +def fx() -> Fixtures: return Fixtures("glitchtip") @pytest.fixture def glitchtip_server_full_api_response( httpretty: httpretty_module, glitchtip_url: str, fx: Fixtures -): +) -> None: """Text fixture. See reconcile/glitchtip/README.md for more details. diff --git a/reconcile/test/glitchtip/test_glitchtip.py b/reconcile/test/glitchtip/test_glitchtip.py index a865076ec..6fd293bdb 100644 --- a/reconcile/test/glitchtip/test_glitchtip.py +++ b/reconcile/test/glitchtip/test_glitchtip.py @@ -1,8 +1,11 @@ +from pytest_mock import MockerFixture + from reconcile.glitchtip.integration import ( fetch_current_state, fetch_desired_state, ) from reconcile.gql_definitions.glitchtip.glitchtip_project import GlitchtipProjectsV1 +from reconcile.test.fixtures import Fixtures from reconcile.utils.glitchtip import ( GlitchtipClient, Organization, @@ -26,8 +29,10 @@ def sort_all(orgs: list[Organization]) -> list[Organization]: def test_fetch_current_state( - glitchtip_client: GlitchtipClient, glitchtip_server_full_api_response, fx -): + glitchtip_client: GlitchtipClient, + glitchtip_server_full_api_response: None, + fx: Fixtures, +) -> None: current_state = fetch_current_state( glitchtip_client, ignore_users=["sd-app-sre+glitchtip@nasa.com"] ) @@ -38,7 +43,7 @@ def test_fetch_current_state( assert sort_all(current_state) == sort_all(expected_current_state) -def test_desire_state(mocker, fx): +def test_desire_state(mocker: MockerFixture, fx: Fixtures) -> None: projects = [ GlitchtipProjectsV1(**i) for i in fx.get_anymarkup("desire_state_projects.yml") ] diff --git a/reconcile/test/glitchtip/test_glitchtip_reconciler.py b/reconcile/test/glitchtip/test_glitchtip_reconciler.py index 96ea10735..22f44cdaa 100644 --- a/reconcile/test/glitchtip/test_glitchtip_reconciler.py +++ b/reconcile/test/glitchtip/test_glitchtip_reconciler.py @@ -6,6 +6,7 @@ import httpretty as httpretty_module import pytest from pydantic import BaseModel +from pytest_mock import MockerFixture from reconcile.glitchtip.reconciler import GlitchtipReconciler from reconcile.test.fixtures import Fixtures @@ -26,7 +27,9 @@ class GlitchtipUrl(BaseModel): @pytest.fixture -def configure_httpretty(httpretty: httpretty_module, glitchtip_url: str): +def configure_httpretty( + httpretty: httpretty_module, glitchtip_url: str +) -> Callable[[list[GlitchtipUrl]], int]: httpretty.Response def f(glitchtip_urls: list[GlitchtipUrl]) -> int: @@ -49,7 +52,7 @@ def f(glitchtip_urls: list[GlitchtipUrl]) -> int: @pytest.mark.parametrize("dry_run", [True, False]) def test_glitchtip_reconciler_init( glitchtip_client_minimal: GlitchtipClient, dry_run: bool -): +) -> None: gtr = GlitchtipReconciler(client=glitchtip_client_minimal, dry_run=dry_run) assert gtr.client == glitchtip_client_minimal assert gtr.dry_run == dry_run @@ -64,8 +67,8 @@ def test_glitchtip_reconciler_reconcile_users( httpretty: httpretty_module, glitchtip_client_minimal: GlitchtipClient, fx: Fixtures, - configure_httpretty: Callable, -): + configure_httpretty: Callable[[list[GlitchtipUrl]], int], +) -> None: fixture = fx.get_anymarkup(f"reconciler/users/{fixture_name}.yml") current_users = [User(**i) for i in fixture["current_users"]] desired_users = [User(**i) for i in fixture["desired_users"]] @@ -99,8 +102,8 @@ def test_glitchtip_reconciler_reconcile_teams( httpretty: httpretty_module, glitchtip_client_minimal: GlitchtipClient, fx: Fixtures, - configure_httpretty: Callable, -): + configure_httpretty: Callable[[list[GlitchtipUrl]], int], +) -> None: fixture = fx.get_anymarkup(f"reconciler/teams/{fixture_name}.yml") organization_users = [User(**i) for i in fixture["organization_users"]] current_teams = [Team(**i) for i in fixture["current_teams"]] @@ -136,8 +139,8 @@ def test_glitchtip_reconciler_reconcile_projects( httpretty: httpretty_module, glitchtip_client_minimal: GlitchtipClient, fx: Fixtures, - configure_httpretty: Callable, -): + configure_httpretty: Callable[[list[GlitchtipUrl]], int], +) -> None: fixture = fx.get_anymarkup(f"reconciler/projects/{fixture_name}.yml") organization_teams = [Team(**i) for i in fixture["organization_teams"]] current_projects = [Project(**i) for i in fixture["current_projects"]] @@ -173,9 +176,9 @@ def test_glitchtip_reconciler_reconcile_organization( httpretty: httpretty_module, glitchtip_client_minimal: GlitchtipClient, fx: Fixtures, - configure_httpretty: Callable, - mocker, -): + configure_httpretty: Callable[[list[GlitchtipUrl]], int], + mocker: MockerFixture, +) -> None: fixture = fx.get_anymarkup(f"reconciler/organizations/{fixture_name}.yml") current_organizations = [ Organization(**i) for i in fixture["current_organizations"] diff --git a/reconcile/test/glitchtip/test_utils_glitchtip_client.py b/reconcile/test/glitchtip/test_utils_glitchtip_client.py index bc49a2041..2cf293f4e 100644 --- a/reconcile/test/glitchtip/test_utils_glitchtip_client.py +++ b/reconcile/test/glitchtip/test_utils_glitchtip_client.py @@ -1,5 +1,9 @@ import json -from typing import Optional +from collections.abc import Mapping +from typing import ( + Any, + Optional, +) import httpretty as httpretty_module import pytest @@ -89,7 +93,7 @@ def test_get_next_url( def test_glitchtip_client_list( httpretty: httpretty_module, glitchtip_client: GlitchtipClient, glitchtip_url: str -): +) -> None: first_url = f"{glitchtip_url}/data" second_url = f"{glitchtip_url}/data2" @@ -113,7 +117,7 @@ def test_glitchtip_client_list( def test_glitchtip_client_get( httpretty: httpretty_module, glitchtip_client: GlitchtipClient, glitchtip_url: str -): +) -> None: url = f"{glitchtip_url}/data" test_obj = {"test": "object"} httpretty.register_uri( @@ -124,15 +128,19 @@ def test_glitchtip_client_get( def test_glitchtip_client_post( httpretty: httpretty_module, glitchtip_client: GlitchtipClient, glitchtip_url: str -): +) -> None: url = f"{glitchtip_url}/data" request_data = {"test": "object"} response_data = {"foo": "bar"} - def request_callback(request, uri, response_headers): + def request_callback( + request: httpretty_module.core.HTTPrettyRequest, + uri: str, + response_headers: Mapping[str, Any], + ) -> tuple[int, Mapping[str, Any], str]: assert request.headers.get("Content-Type") == "application/json" assert json.loads(request.body) == request_data - return [201, response_headers, json.dumps(response_data)] + return (201, response_headers, json.dumps(response_data)) httpretty.register_uri( httpretty.POST, url, content_type="text/json", body=request_callback @@ -142,15 +150,19 @@ def request_callback(request, uri, response_headers): def test_glitchtip_client_put( httpretty: httpretty_module, glitchtip_client: GlitchtipClient, glitchtip_url: str -): +) -> None: url = f"{glitchtip_url}/data" request_data = {"test": "object"} response_data = {"foo": "bar"} - def request_callback(request, uri, response_headers): + def request_callback( + request: httpretty_module.core.HTTPrettyRequest, + uri: str, + response_headers: Mapping[str, Any], + ) -> tuple[int, Mapping[str, Any], str]: assert request.headers.get("Content-Type") == "application/json" assert json.loads(request.body) == request_data - return [201, response_headers, json.dumps(response_data)] + return (201, response_headers, json.dumps(response_data)) httpretty.register_uri( httpretty.PUT, url, content_type="text/json", body=request_callback @@ -158,40 +170,40 @@ def request_callback(request, uri, response_headers): assert glitchtip_client._put(url, data=request_data) == response_data -def test_glitchtip_organizations(glitchtip_client: GlitchtipClient): +def test_glitchtip_organizations(glitchtip_client: GlitchtipClient) -> None: assert glitchtip_client.organizations() == [ Organization(id=10, name="ESA", slug="esa", projects=[], teams=[], users=[]), Organization(id=4, name="NASA", slug="nasa", projects=[], teams=[], users=[]), ] -def test_glitchtip_create_organization(glitchtip_client: GlitchtipClient): +def test_glitchtip_create_organization(glitchtip_client: GlitchtipClient) -> None: org = glitchtip_client.create_organization(name="ASA") assert org.name == "ASA" assert org.slug == "asa" -def test_glitchtip_delete_organization(glitchtip_client: GlitchtipClient): +def test_glitchtip_delete_organization(glitchtip_client: GlitchtipClient) -> None: glitchtip_client.delete_organization(slug="esa") -def test_glitchtip_teams(glitchtip_client: GlitchtipClient): +def test_glitchtip_teams(glitchtip_client: GlitchtipClient) -> None: assert glitchtip_client.teams(organization_slug="nasa") == [ Team(id=4, slug="nasa-flight-control", users=[]), Team(id=2, slug="nasa-pilots", users=[]), ] -def test_glitchtip_create_team(glitchtip_client: GlitchtipClient): +def test_glitchtip_create_team(glitchtip_client: GlitchtipClient) -> None: team = glitchtip_client.create_team(organization_slug="esa", slug="launchpad-crew") assert team.slug == "launchpad-crew" -def test_glitchtip_delete_team(glitchtip_client: GlitchtipClient): +def test_glitchtip_delete_team(glitchtip_client: GlitchtipClient) -> None: glitchtip_client.delete_team(organization_slug="esa", slug="esa-pilots") -def test_glitchtip_projects(glitchtip_client: GlitchtipClient): +def test_glitchtip_projects(glitchtip_client: GlitchtipClient) -> None: assert glitchtip_client.projects(organization_slug="nasa") == [ Project( id=8, @@ -213,7 +225,7 @@ def test_glitchtip_projects(glitchtip_client: GlitchtipClient): ] -def test_glitchtip_create_project(glitchtip_client: GlitchtipClient): +def test_glitchtip_create_project(glitchtip_client: GlitchtipClient) -> None: project = glitchtip_client.create_project( organization_slug="nasa", team_slug="nasa-pilots", @@ -225,26 +237,26 @@ def test_glitchtip_create_project(glitchtip_client: GlitchtipClient): assert project.teams[0].pk == 2 -def test_glitchtip_delete_project(glitchtip_client: GlitchtipClient): +def test_glitchtip_delete_project(glitchtip_client: GlitchtipClient) -> None: glitchtip_client.delete_project( organization_slug="nasa", team_slug="nasa-pilots", slug="science-tools" ) -def test_glitchtip_add_project_to_team(glitchtip_client: GlitchtipClient): +def test_glitchtip_add_project_to_team(glitchtip_client: GlitchtipClient) -> None: project = glitchtip_client.add_project_to_team( organization_slug="nasa", team_slug="nasa-flight-control", slug="science-tools" ) assert len(project.teams) == 2 -def test_glitchtip_remove_project_from_team(glitchtip_client: GlitchtipClient): +def test_glitchtip_remove_project_from_team(glitchtip_client: GlitchtipClient) -> None: glitchtip_client.remove_project_from_team( organization_slug="nasa", team_slug="nasa-flight-control", slug="science-tools" ) -def test_glitchtip_organization_users(glitchtip_client: GlitchtipClient): +def test_glitchtip_organization_users(glitchtip_client: GlitchtipClient) -> None: assert glitchtip_client.organization_users(organization_slug="nasa") == [ User(id=23, email="MichaelCollins@nasa.com", role="member", pending=False), User( @@ -259,7 +271,7 @@ def test_glitchtip_organization_users(glitchtip_client: GlitchtipClient): ] -def test_glitchtip_invite_user(glitchtip_client: GlitchtipClient): +def test_glitchtip_invite_user(glitchtip_client: GlitchtipClient) -> None: user = glitchtip_client.invite_user( organization_slug="nasa", email="Gene.Kranz@nasa.com", role="member" ) @@ -267,18 +279,18 @@ def test_glitchtip_invite_user(glitchtip_client: GlitchtipClient): assert user.pending -def test_glitchtip_delete_user(glitchtip_client: GlitchtipClient): +def test_glitchtip_delete_user(glitchtip_client: GlitchtipClient) -> None: glitchtip_client.delete_user(organization_slug="nasa", pk=29) -def test_glitchtip_update_user_role(glitchtip_client: GlitchtipClient): +def test_glitchtip_update_user_role(glitchtip_client: GlitchtipClient) -> None: user = glitchtip_client.update_user_role( organization_slug="nasa", role="manager", pk=29 ) assert user.role == "manager" -def test_glitchtip_team_users(glitchtip_client: GlitchtipClient): +def test_glitchtip_team_users(glitchtip_client: GlitchtipClient) -> None: assert glitchtip_client.team_users( organization_slug="nasa", team_slug="nasa-flight-control" ) == [ @@ -292,14 +304,14 @@ def test_glitchtip_team_users(glitchtip_client: GlitchtipClient): ] -def test_glitchtip_add_user_to_team(glitchtip_client: GlitchtipClient): +def test_glitchtip_add_user_to_team(glitchtip_client: GlitchtipClient) -> None: team = glitchtip_client.add_user_to_team( organization_slug="nasa", team_slug="nasa-pilots", user_pk=29 ) assert len(team.users) > 0 -def test_glitchtip_remove_user_from_team(glitchtip_client: GlitchtipClient): +def test_glitchtip_remove_user_from_team(glitchtip_client: GlitchtipClient) -> None: glitchtip_client.remove_user_from_team( organization_slug="nasa", team_slug="nasa-pilots", user_pk=29 ) diff --git a/reconcile/test/glitchtip/test_utils_glitchtip_models.py b/reconcile/test/glitchtip/test_utils_glitchtip_models.py index 72eaf0f56..f9c3dbfd2 100644 --- a/reconcile/test/glitchtip/test_utils_glitchtip_models.py +++ b/reconcile/test/glitchtip/test_utils_glitchtip_models.py @@ -1,3 +1,6 @@ +from collections.abc import Mapping +from typing import Union + import pytest from reconcile.utils.glitchtip import ( @@ -19,19 +22,23 @@ ], ) @pytest.mark.parametrize("model", [Organization, Project, Team]) -def test_model_slugs(model, name, slug): +def test_model_slugs( + model: Union[type[Organization], type[Project], type[Team]], name: str, slug: str +) -> None: assert model(name=name).slug == slug @pytest.mark.parametrize( "team_kwargs", [ - pytest.param({"name": "Test", "slug": "Test 1 2 3"}, marks=pytest.mark.xfail), + pytest.param( + {"name": "Test", "slug": "Test 1 2 3"}, marks=pytest.mark.xfail(strict=True) + ), {"name": "Test 1 2 3"}, {"slug": "test-1-2-3"}, ], ) -def test_model_team(team_kwargs): +def test_model_team(team_kwargs: Mapping[str, str]) -> None: slug = slugify("Test 1 2 3") team = Team(**team_kwargs) assert team.name == slug diff --git a/setup.cfg b/setup.cfg index 2e7c09b78..29614ec2e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -565,6 +565,10 @@ check_untyped_defs = False [mypy-reconcile.test.test_gitlab_housekeeping] check_untyped_defs = False +[mypy-reconcile.test.glitchtip.*] +disallow_untyped_defs = True +disallow_incomplete_defs = True + [mypy-reconcile.test.test_ocm_upgrade_scheduler] check_untyped_defs = False