티스토리 뷰

파이썬

Pytest reportlog 에 PR 후기 및 그리고 사용방법

글을 쓰는 개발자 2022. 2. 19. 21:09
반응형

1. 문제점

  • 사람이 보기가 힘들다
  • 내가 보고 싶은 outcome만 보는 것이 힘들다.

 

회사 내에서 장고 버전을 1.11 -> 3.2 로 올라가면서 pytest resultlog가 removed가 되고 reportlog로 대체되었는데 정말 가독성이 안좋아졌다.

 

다음과 같이 생긴 로그들이 기본적으로 제공하는 로그들이다.

 

 

제가 할 수 있는 방법은 다음 두가지가 있었습니다.

  • 생성된 파일을 re building하는 방식
  • 애초에 생성할 때 내가 원하는 내용을 출력해주는 방식

 

저는 두 방식중 생성할 때 내가 원하는 내용을 출력해주는 것이 더 좋은 방법이라고 생각해서 튜닝 작업을 나서기 시작했습니다.

 

1. 커멘드 라인 추가 설정

    group.addoption(
        "--summary-report-level",
        '--srl',
        action="store",
        metavar="LEVEL-INFO",
        default="none",
        help="choose outcome level [ 'none', 'passed', 'skipped', 'failed'] "
    )

 

2. outcome 에 따른 쓰기 작업하는 메소드 수정

    def _write_json_data(self, data):
        if self._summary_report_level == 'none':
            self._write_default_json_data(data)
        else:
            self._write_summary_json_data(data)

    def _write_default_json_data(self, data):
        try:
            json_data = json.dumps(data)
        except TypeError:
            data = cleanup_unserializable(data)
            json_data = json.dumps(data)
        self._file.write(json_data + "\n")
        self._file.flush()

    def _write_summary_json_data(self, data):
        suffix = ",\n"
        prefix = ""
        json_data = ""
        try:
            outcome = data.get("outcome")
            if outcome and self._check_outcome(outcome):
                data = self._format_summary_report_data(data, outcome)
                json_data = json.dumps(data, ensure_ascii=False)
            elif data.get("pytest_version", None) is not None:
                json_data = json.dumps(data, ensure_ascii=False)
                prefix = "["
            elif data.get("exitstatus", None) is not None:
                json_data = json.dumps(data, ensure_ascii=False)
                suffix = "]"
            else:
                pass
        except TypeError:
            data = cleanup_unserializable(data)
            json_data = json.dumps(data)
        if json_data == "":
            suffix = ""
        self._file.write(prefix + json_data + suffix)
        self._file.flush()

    def _check_outcome(self, outcome):
        level = ["passed", "skipped", "failed"]
        if self._summary_report_level == "skipped":
            level = level[1:]
        if self._summary_report_level == "failed":
            level = level[2:]

        return outcome in level

    def _format_summary_report_data(self, data, outcome):
        add_data = {}
        if outcome not in ("skipped", "passed"):
            add_data["message"] = data["longrepr"]["reprcrash"]["message"]
        if data.get("location"):
            data = {"outcome": outcome, "location": data["location"]}
        elif outcome == "passed":
            return {}
        data.update(add_data)
        return data

 

3. 테스트케이스 작성 (일부분만..)

def test_report_srl_failed(testdir, tmp_path, pytestconfig):
    testdir.makepyfile(
        """
        def test_ok():
            pass
        def test_fail():
            assert 0
    """
    )

    log_file = tmp_path / "log.json"

    result = testdir.runpytest("--report-log", str(log_file), "--srl", "failed")
    assert result.ret == pytest.ExitCode.TESTS_FAILED
    result.stdout.fnmatch_lines(["* generated report log file: {}*".format(log_file)])
    json_objs = json.loads(log_file.read_text())
    only_failed_test = json_objs[1]
    assert only_failed_test.keys() == {"outcome", "location", "message"}
    assert only_failed_test.get("outcome") == "failed"
    assert only_failed_test.get("message") == "assert 0"
    
    def test_report_srl_skipped(testdir, tmp_path, pytestconfig):
    testdir.makepyfile(
        """
        import sys
        import pytest
        def test_ok():
            pass
        
        def test_skip():
            if not sys.platform.startswith("win"):
                pytest.skip("skipping windows-only tests", allow_module_level=True)
        def test_fail():
            assert 0
    """
    )

    log_file = tmp_path / "log.json"

    result = testdir.runpytest("--report-log", str(log_file), "--srl", "skipped")
    assert result.ret == pytest.ExitCode.TESTS_FAILED
    result.stdout.fnmatch_lines(["* generated report log file: {}*".format(log_file)])
    json_objs = json.loads(log_file.read_text())
    for obj in json_objs:
        if obj.get("outcome") == "skipped":
            assert obj.keys() == {"outcome", "location"}
        elif obj.get("outcome") == "failed":
            assert obj.keys() == {"outcome", "location", "message"}

 

1. 오픈소스에 PR 해보기

https://github.com/pytest-dev/pytest-reportlog/pull/14

 

add command line flag by VIXXPARK · Pull Request #14 · pytest-dev/pytest-reportlog

--summary-report-level or --srl level status = [ "none", "passed", "skipped", "failed"] format example { "outcome" : "failed", "location" : [...], "message" : "AssertionError ..." } me...

github.com

그 결과는 Closed 였다. 이유는 간단했다. 해당 플러그인은 사람이 보기 위해서 만들어진 플러그인이 아니고, 프로그램이 해당 플러그인으로 만들어진 파일을 토대로 유의미한 결과에 사용하는데 쓰이기 때문에 만일 보기가 힘들다면 pytest-html을 쓰라고 권장한 다음 거절당했다.

 

하지만 나 그리고 회사 사람들 경우에는 html까지 생성을 해서 보는 것은 too much하다는 생각을 가지게 되었고,  다른 대안으로 제가 수정한 브랜치를 특정해서 pip 목록에 추가하기로 하였다.

 

 

특정 브랜치 사용법

-e git://github.com/VIXXPARK/pytest-reportlog.git@feature/summary_report_level#egg=pytest-reportlog

requirements.txt에 해당 내용을 추가하시면 됩니다.

 

그리고 사용방법은 위의 PR을 참고해주시면 됩니다.

 

좀 더 자세한 내용을 보고 싶으시면  https://github.com/VIXXPARK/pytest-reportlog/tree/feature/summary_report_level 

 

GitHub - VIXXPARK/pytest-reportlog: Replacement for the --resultlog option, focused in simplicity and extensibility

Replacement for the --resultlog option, focused in simplicity and extensibility - GitHub - VIXXPARK/pytest-reportlog: Replacement for the --resultlog option, focused in simplicity and extensibility

github.com

해당 github 주소를 들어가서 봐주시면 감사하겠습니다.

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함