Backend MLOps/Fastapi

[Github Action] python 프로젝트의 coverage 측정 후 보고

SteadyForDeep 2021. 9. 23. 22:35
반응형

//coverage란?

 

작성된 코드는 어떤 목적을 가지고 만들어진 로직의 집합니다.

따라서 작성자는 본인이 작성한 코드가 어떤 동작을 수행해야하는지

정확하게 알고 있는 몇 안되는 사람이고 그에 맞게 바르게 이해하고 있어야 한다.

 

보통 파이썬은 아주 작은 단위의 객체들이 모여서 하나의 큰 프로젝트를 만들게 되므로

이 작은 단위의 객체들이 모두 자기 역할을 충실히 하는지 테스트 하면

큰 프로젝트를 모두 돌려보지 않더라도 전체 프로젝트의 신뢰도를 예측할 수 있다.

 

이렇게 자신의 코드가 예상대로 움직여주는지 확인하는 작업을 unittest라고 하고

자신이 만든 객체들 중 몇 퍼센트가 테스트되고 있는지 확인해 알려주는 지표가

바로 coverage값이라고 할 수 있다.

 

 

//Github Action?

 

우리는 이 값을 github에 전송할때마다 측정하여

매번 버전이 바뀔때마다 상승하는지 하락하는지 채크하고 유지하여

코드의 성능이 버전이 갈수록 떨어지는 현상을 막을 수 있다.

 

github에서는 action 이라는 서비스를 제공하는데

특정 조건이 충족되면 가상머신을 할당받아

머신 위에서 미리 짜여진 동작을 수행할 수 있는 서비스다.

 

굉장히 간단한 작업으로 push 가 동작할때마다 coverage를 측정할 수 있도록 할 수 있다.

우선은 github에 올라갔을 때 github이 파일들을 딱 보고

정해진 어떤 패턴의 파일이 있으면 아 이거 Action하라는 말이구나

하고 Action을 동작해 준다.

바로 git repository에 .github/workflows/ 라는 디렉토리를 만들고

거기에 하고싶은 동작이 담겨있는 yaml 파일을 넣어 주면 그 파일에 있는 동작들을 수행해 준다.

 

 

// 실습

 

간단한 레포 하나를 뚫어준다.

이걸 가지고 이제 액션을 해보자.

 

여러가지 방법이 있지만 나는 깃헙에서 수정하는 것을 크게 좋아하지 않으므로

로컬에서 작업하는 것을 기준으로 설명을 진행하겠다.

간단한 코드를 하나 짰다.

https://pypi.org/project/coverage/

 

coverage

Code coverage measurement for Python

pypi.org

그리고 coverage를 깔아준다. 요놈을 통해서 내가 내 코드를 얼마나 커버하고 있는지 알아보자.

 

우선은 위에 설명한대로 내 코드를 커버해줄 unittest를 만들어야 coverage를 측정할 수 있다.

 

 

위에서 만든 코드랑 같은 위치에 하나 만들었다.

테스트를 위해서 사용되는 모듈은 unittest를 사용한다.

저기서 main의 name이 "world"가 아니면 에러가 발생할 것이다.

돌려보면 1개의 테스트가 잘 돌아갔고 모두 통과라고 한다.

그러면 이번에는 좀 더 어렵게 해보자.

main에 길이 10짜리 스트링을 넣고 길이가 10이랑 같지 않으면 오류가 발생하게 했다. 

테스트가 하나 늘어서 2개가 수행되었다고 나오고 모두 통과했다.

 

그런데 이건 그냥 테스트고 이걸 돌린다고 coverage가 측정이 되는건 아니다.

coverage를 이용하는 방법은 아래의 코드를 실행하는 것이다.

동일한 결과가 나왔지만 전혀 다른 코드가 실행된 것이다.

coverage run은 coverage 를 측정하라는 것이고

source 는 어떤 범위의 디렉토리에서 검사를 측정할 것이냐

그리고 -m 은 unittest 모듈을 이용해서

이하 모든 디렉토리의 발견된 _test.py로 끝나는 파일을 실행한 결과를 보라는 말이다.

이렇게 돌리고 나면 리포트가 하나 생겨있다.

저기에 내가 소스로 지정한 코드들이 얼마나 coverage가 높은지 저장되어 있다.

 

이렇게 확인해 보면 각각 얼마나 많은 코드들이 최소한 한번은 동작하여

오류가 있는지 없는지 확인이 되었나 볼 수 있다.

그런데 웃긴게 우리가 test파일이라고 만든 놈도 100%가 되지 않는다.

그 이유는 if문 때문인데

if __name__ == "__main__":

이부분이 맞고 틀리고가 모두 측정되지 않았기 때문에 그만큼 떨어진 수치가 측정되었다.

요렇게 if문은 검사에서 빼라

라는 명령을 달아주면 이녀석이 알아서 저 부분은 총 평가에서 빼준다.

100%로 오른 것을 볼 수 있다.

main도 동일하게 해주면 88%로 찍힌다.

이제 동일한 결과를 얻으면서 자동으로 push가 될때마다 이 작업이 수행되도록 해보자.

 

위에서 언급한 디렉토리와 파일을 만들어줬다.

이제 이 파일을 작성하기만 하면 된다.

사실 github에서 action 탭으로 가면 이 파일을 잘 세팅할 수 있는 도움자료가 많지만

간단한 커버리지만 측정하도록 해보자.

보면 맨 위는 이 작업의 이름이 되고

on이 바로 어떤 동작일때 함께 수행하겠냐 하는 조건이다.

그 이하로 여러가지 작업들을 나열할 수 있고

나는 하나씩 step을 밟아가면서 작업할 것을 요구했다.

무선은 파이썬을 설치하고

pip를 업그레이드 하여 coverage를 깔고난 다음

coverage를 이용해서 모든 테스트를 실행한 후

리포트를 만들도록 했다.

 

중요한 것은 이 yaml 파일이 반드시 upload 되는 파일중에 포함되어 있어야한다는 것이다.

.gitignore 에서 무지성으로 .* 같은 애들을 죽이다가

이 파일도 열외되는 경우가 있으니 주의.

 

이게 push를 해보면

pull requests 가 만들어지고 무엇인가 진행중인 것을 알 수 있다.

오른쪽에 Details 를 눌러서 확인하면

내가 이름붙인 일련의 과정들이 수행되었고

동일한 결과를 얻은 것을 볼 수 있다.

이제 이 기능을 이용하면 테스트에 실패한 커밋을 merge 전에 찾아내서 차단한다던지

이전보다 더 coverage가 떨어진건 아닌지 등을 관찰하면서 github을 관리할 수 있다.

반응형