첫 번째python 패키지 작성에서 얻은 경험과 교훈

내가 첫 번째python 패키지를 작성할 때 배운 경험과 교훈의 간단한 요약: taggercoretaggercli.
그들에 대한 더 많은 정보는 여기서 찾을 수 있다.


의존 관계 관리


의존 관계 관리는 모든 항목에 매우 중요하다.
나는 우연히 이 stackoverflow post을 발견할 때까지 패키지 의존항과 개발 의존항을 분리하는 매우 만족스러운 해결 방안을 찾을 수 없다.
나는 setup.py에서 모든 가방 의존항을 지정했다.
설정 방법은 extras_require이라는 선택할 수 있는 매개 변수를 제공합니다.이 매개 변수는 패키지와 개발자 의존항을 분리하는 데 도움이 됩니다.

설치.회사 명


setup(
    name="somepackage",
    version="1.0.0",
    install_requires=["boto3"],
    extras_require={"dev": ["pytest", "tox", "pytest-cov", "pytest-mock", "black"]}
)
보시다시피,pytest,tox,black과 두pytest 플러그인을 제 개발 추가 플러그인으로 지정합니다.
현재 dev extras를 포함하여 pip install -e .[dev] (또는 zsh:pip install -e ".[dev]"에서) 패키지 의존항을 간단하게 설치할 수 있습니다.
개발 의존 항목이 필요하지 않으면 pip install -e .을 실행하십시오

독물

extras_require은 tox와 결합할 때 모든 출력을 표시합니다.
설치할 추가 항목의 키만 지정하면 됩니다 (예: "dev").Tox는 환경에 모든 의존 항목을 설치해야 합니다.

독극물회사 명


[tox]
envlist = py38

[testenv]
extras = dev
commands = pytest 
내가 보기에 이런 의존 관계 관리 방법은 매우 편안하다.패키지 의존항과 개발 의존항의 분리를 유지하는 것은 나에게 매우 중요하다.
당신은python 의존 관계를 어떻게 관리합니까?

테스트


시뮬레이션 단언 이해


tagger 프로젝트가 시작되었을 때, 나는python으로 테스트를 작성하는 것이 매우 낯설었다.
나는python 시뮬레이션 대상의 강력한 기능을 이해하는 데 오랜 시간이 걸렸다.
아날로그 객체는 다음과 같은 유용한 설명을 제공합니다.
- assert_called
- assert_called_with_once
- assert_any_call
...
전체 목록은 documentation을 참조하십시오.
여러 호출을 단언해야 하는 경우 다음을 사용할 수 있습니다.assert_has_callsunittest.mock.call objects의 배열(예:

태그 코어//test\u region\u tagger/test\u should\u split\u 리소스


# shortened for readability
mocked_init_client.return_value.tag_resources.assert_has_calls(
            [
                call(
                    ResourceARNList=[
                        "some-arn-1",
                        "some-arn-2"
                    ],
                    Tags=expected_tags
                ),
                call(
                    ResourceARNList=[
                          "some-arn-3",
                          "some-arn-4"
                    ],
                    Tags=expected_tags
                )
            ],
            any_order=True
)

수리의 작업 원리를 이해하다


수선하다
패치를 사용하면 런타임 시 객체의 동작을 조작할 수 있습니다.이것은 테스트 기간에 의존 관계를 모의하는 매우 강력한 방법이다.
만약 자바 배경이 있다면, 예를 들면, 아날로그 대상을 만드는 데 사용할 수 있는 mockito 라이브러리를 알고 있을 것입니다.
python에서 이것은 패치 방법을 통해 실현할 수 있다.그러나 패치 목표를 정확하게 정하는 것은 좀 어렵다.
나는 이 pycon talk의 패치 함수의 베일을 벗기는 것에 관한 글을 강력히 추천한다.
요점: "작성 위치가 아닌 객체의 사용 위치 패치"
예를 들어 이 견해를 밝히겠습니다.
taggercli 패키지는 taggercore에서 만든 클래스와 함수를 사용합니다.
taggercli/commands/tag에서 다음을 찾을 수 있습니다.from taggercore.usecase import scan_region_and_global우리는 어떻게 이 전화를 비웃습니까?
사용 시: taggercli.commands.tag.scan_region_and_global 패치 대신 taggercore.usecase.scan_region_and_global
scan_mock = mocker.patch(
        "taggercli.commands.tag.scan_region_and_global",
        return_value=scanned_resources,
)
(mocker은pytest 클러치로 아날로그 패키지에 좋은 API를 제공)
오류 수정된 아날로그 객체를 계속 디버깅하는 경우 dir() 명령이 도움이 될 수 있습니다.
이것은python 파일에서 함수와 클래스에 접근하는 방법에 대한 힌트를 제공할 수 있습니다.

pytest 클러치를 안는 힘


고정 장치 주입 테스트


보시다시피 특히 taggerlambda/test/test_lambda.py에서 저는 pytest-fixtures을 광범위하게 사용했습니다.
나는 그것으로 간단한 "거짓"데이터를 제공한다.

taggerlambda/test/test_lambda。회사 명


@pytest.fixture(scope="module")
def tagging_result(regional_resources, global_resources) -> TaggingResult:
    successful_arns = [resource.arn for resource in regional_resources] + [
        resource.arn for resource in global_resources
    ]
    yield TaggingResult(successful_arns, {})
이제 테스트 매개변수 목록에 고정장치 이름을 추가하여 테스트에서 고정장치를 사용할 수 있습니다.

taggerlambda/test/test\u lambda/test\u lambda\u in\u tag\u mode\u env


def test_lambda_in_tag_mode_env(
        self,
        tagging_result # the object is injected by pytest automatically
        .....
    ):
    .....

    mocked_perform_tagging = mocker.patch("src.tagging_lambda.perform_tagging")
    mocked_perform_tagging.return_value = tagging_result

    ....

고정 장치를 고정 장치에 주입하다


테스트에서 다른 하위 대상으로 구성된 더 복잡한 대상이 필요합니까?
이것은 다른 집게에서 집게를 다시 사용해서 쉽게 실현할 수 있다.
다음 예제를 참조하십시오.
각 리소스 객체에는 다음과 같은 태그 객체 목록이 있습니다.

taggerlambda/test/test_lambda。회사 명


@pytest.fixture(scope="module")
def tags() -> List[Tag]:
    yield [
        Tag("Project", "CoolProject"),
        Tag("Owner", "Fritz")
    ]
그런 다음 다른 고정장치에서 태그 고정장치를 다시 사용할 수 있습니다.
@pytest.fixture(scope="module")
def regional_resources(tags) -> List[Resource]:
    yield [
        Resource("some-arn-1", "someq", "queue", tags),
        Resource("some-arn-2", "someq2", "queue", tags)
    ]

운영 환경 변수


테스트 코드에서 환경 변수를 사용하면pytestfixture를 통해 완전히 설정된 환경을 쉽게 제공할 수 있습니다.
@pytest.fixture(scope="function")
def env_for_tag_mode_env(monkeypatch):
    config = {
        "ACCOUNT_ID": "111111111111",
        "TAG_MODE": "ENV"
    }
    monkeypatch.setenv("ACCOUNT_ID", config["ACCOUNT_ID"])
    monkeypatch.setenv("TAG_MODE", config["TAG_MODE"])
    yield config
테스트 코드의 단언 부분에 현재 환경이 어떻게 설정되어 있는지 알 수 있도록configdict를 생성합니다.monkeypatch 클러치는pytest에 포함되어 있으며, 예를 들어 setenvdelenv이게 다 내가 말한 거야!
내 글을 읽어줘서 고마워요. 내 총결에서 이득을 봤으면 좋겠어요.)

좋은 웹페이지 즐겨찾기