일상적 이야기들.

[TIL] Pytest - mock server 구축 본문

프로그래밍/PYTHON

[TIL] Pytest - mock server 구축

noveljava 2020. 9. 23. 00:06

TestCode

지금 있는 속한 팀에 있기 전, 바로 직전에는 QA팀에서 Tool을 만들었다. 그때도 동일하게 테스트코드를 작성을 하였지만, 이 글에서 이야기하는 테스트코드와는 결이 달랐다.
개발자가 자신이 작성한 코드에 대한 최소한의 보증수표를 붙혀주는 것이 TestCase 작성인 것 같다.
하지만 개발자가 작성하는 TestCase에는 함정이 있을 수도 있다. 왜냐하면 자신이 작성한 코드이기때문에 방어적으로 코드를 작성하게 되는 것 같다. 실 사용자들은 기상천외한 값들을 넣을 수 있기때문에 따로 QA팀이 있고, 해당 팀에서 매뉴얼로든 프로그램이든 여러가지 케이스를 테스트하게 된다.
그 중에 나는 End-User 입장에서 테스트코드를 작성을 하였기에, PyTest로 작성하는 코드와는 달랐다.

Pytest

Python에서 제공하는 TestCase Framework이다. 이를 이용해서 개발자가 작성한 모듈들에 대한 TestCase를 작성하여 최소한의 사용법과 안정성을 제공해줄 수 있다.
이번 기회에 해당 프레임워크로 TestCase를 작성을 해보았고, 다음과 같은 문제점들에 대해서 해결을 하기 위해서 노력을 하였다.

1. File Donwload를 위해서, request를 하는 부분에 대한 TestCase 작성.

테스트해야하는 모듈 중에서는, domain주소로 요청을 하여 local에 파일을 다운하여, 압축을 풀고 파일을 정상적으로 다운이 되었는지 검사하는 모듈이 존재하였다.
단순히 domain주소가 언제나 살아있으면 좋은 테스트코드를 작성할 수 있겠지만, 해당 ftp server 또한 팀원이 작성한 코드였기때문에 상시적으로 올라가있는 서버가 아니어서 문제가 발생을 하였다.
이에 TestCase 내에서 ftp server를 mock-up 으로 구성을 해야했었고, 이를 다음과 같이 구현을 하여 처리를 하였다.

  
    from httpretty import HTTPretty, httprettified
    def ftp_server_for_test(self):
        # test response mocking
        this_dir, _ = os.path.split(__file__)
        tgz_file_path = os.path.join(this_dir, "directory_path", "wanna_file.tgz")

        url = # mockup server address
        with open(tgz_file_path, "rb") as f:
            HTTPretty.register_uri(HTTPretty.GET, f"{url}", body=f.read())

    @httprettified
    def test_case(self):
        ftp_server_for_test()
        url = # mock server address
        urllib.request.urlretrieve(f"{url}", "local path")
  

이렇게 요청 시에, test_case에서 요청되는 request는 ftp_server_for_test에서 정의된 곳을 바라보게 되고, body 내용으로 tgz_file_path의 내용을 던져주게 된다.
tgz 파일은 TestCase와 동일하게 local에 존재하게 된다. 해당 Test에서는 urllib.request.urlretrieve를 위해서 짠 것이 아니라, 다른 서버에 의존성에 의해서 발생하는 TestCase를 인터넷이 접속되지 않는 환경에서도 테스트를 위해서 local에서도 해당 요청이 정상동작하기 위한 mock-up이라는 것이 중요하다.

2. 다른 서버와의 통신

작성된 모듈이, post 방식으로 다른 서버에 정보를 건네주고, response되는 값에 따라 작동을 하는 함수에 대한 TestCase가 필요하다.
이때도 동일하게, 내가 작성된 모듈이 다른 서버의 결과값에 의해서 의존적이게 되어서 request에 대한 mock-up이 필요하다

  
      import requests_mock
    import requests

    def test_register_node(self, node_manager):
        url = # mockup server address
        with requests_mock.Mocker() as mock:
            mock.post(f"{url}",
                      json={"jsonrpc": "2.0", "id": 1234, "result": 0},
                      status_code=200)
            response = requets.post(url)
  

위와 같이 requests_mock을 통하여, 해당 url로 던졌을 때 기대되는 json값과 status_code를 정의를 해주었다.
이러면, 작성된 코드에서는 다른 서버가 어떠한 일을 하는지에 관심이 없고, 오직 통신을 했을 시에 기대되는 값에만 신경을 써 테스트코드가 작성이 가능하다.

'프로그래밍 > PYTHON' 카테고리의 다른 글

Vscode Setting 정보  (0) 2021.01.08
Mac - Bigsur 에서 pyenv 문제  (0) 2021.01.03
[TIL] vscode - organizeImports 설정  (0) 2020.09.17
[TIL] lambda, TeypVar  (0) 2020.09.10
[TIL] vscode - PEP8 관련 설정 잡기.  (0) 2020.09.09
Comments