Pytest 테스트 결과 좀 더 편하게 보기

내가 하는 일 중의 상당 시간은 C++로 소프트웨어를 만드는 일이다. 이중 프로세스 하나의 범위를 벗어난 부분은 C++에서 mocking하거나 혹은 좀 더 넓은 의미로 test-double 을 만드는게 단순하지 않은 것들이 있다. (그리고 C++에서 이런 mock을 작성하는게 그렇게 생산성이 높은 것 같지도 않다)

그래서 잘 만들어진 python 테스트 프레임웍인 pytest를 가져다 쓰기로 했다. 그리고 pytest에서 아래와 같은 식으로 테스트를 한다.

  • 테스트 환경 (DB, redis, …) 초기화; test-suite 혹은 pytest fixture기준으로 모듈마다 실행
  • C++로 작성한 프로세스들을 구동 (이것도 모듈마다)
  • 테스트 케이스 실행; 그리고 이 때 일부 외부 프로세스는 python으로 흉내낸다. (예를 들어 이메일을 보낸다면 smtp 서버를 mocking한다)

여기까진 잘 만들어서 쓰고 있다. 하지만 당연히 예측 가능한 문제들이 터지는데,

  • pytest module 기준 fixture들이 실패하면 테스트가 와장창 깨진다. (외부 프로세스 실행은 그렇게 신뢰성있게 할 수 있는게 아님)
  • 테스트가 오래 걸린다 (초기화 + 프로세스 실행, 끝나고 나서 프로세스 정리).
  • 원격 환경에서 실행하는게 그다지 편하지 않다. 나는 macOS 랩탑에서 작업하고, 빌드/테스트는 모두 내 linux 개발 환경에서 한다.

그래서 테스트 결과를 금방 얻지 못하고, 가끔 와장창 깨지기도 해서 테스트 결과를 좀 더 편하게 받아볼 방법을 찾았다. 처음 선택한 것은 CI 도구에서도 쓰고 있는 pytest-html로 HTML 리포트를 생성하게 하고 이 파일을 로컬에 가져와서 보는 것. 개략적으로 아래처럼 처리하게 했다.

  1. SSH 로 개발 환경에 접속해서 pytest를 실행하고, 실행 인자로 pytest-html 출력물을 구분 가능한 이름으로 생성한다. 이 HTML 리포트는 단일 파일을 생성하게 한다. 대략 이런 식. 일부 테스트만 실행하거나 최대한 빨리 실패하는걸 원할 때 등을 위해서 $@ 으로 인자를 넘길 수 있게 했다.

    #!/bin/bash -e
    pytest -v --rootdir=. --html=report-{REPORT_ID}.html --self-contained-html $@

  2. 빌드가 끝나고 나면 scp 로 1의 결과물을 가져온다.

  3. 그리고 웹 브라우저에 이걸 로드한다. (open -a firefox report-{REPORT_ID}.html 실행)

다만 이렇게 일하는 게 그렇게까지 만족스럽지는 않았다. 추가 의존성이 필요하고 (pytest-html), 테스트 여러번 실행한 후에 헷갈리는 것.(브라우저에 열리는 순서가 그렇게까지 deterministic하지 않은 듯 하다) 그리고 개발에 필요한 도구는 최소화하는게 내 취향이기도 하고. 그래서 몇 주 전부터 아래 방법을 쓰고 있다.

  1. pytest를 unbuffered mode로 실행한다. 색상정보도 포함하게 실행. (python -u -m pytest --color=yes 로 실행)
  2. 1의 결과를 less 로 받아서 출력한다. (less -R 로 ANSI color code처리하게 실행)

이러면 출력 결과물은 좀 덜 아름답지만(?) 테스트 실행은 내가 쓰는 터미널 하나로 끝. 웹 브라우저 없이 / 색상은 유지하면서 실행도 간단한 편. 이 명령을 스크립트에 넣고, 빌드 의존성이랑 같이 몇 주째 쓰고 있고 만족스럽다.