django custom command
를 만들어볼게요.
db가 온전히 실행되기 전에 다른 명령어가 수행되면 안되기에 이를 기다리게! 하기위한 명령어에요.
장고 앱 실행시 docker-compose 파일에 사용하기 위해서에요.
왜냐하면 가끔 장고앱에서 디비 애러를 내서 서버 실행에 실패를 내요.
그래서 db에 완벽히 연결되기 전까지 django실행을 계속 지연시켜줄 소스코드를 짜고 이를 커스텀 명령어로 만들어 줄거에요.
아래와 같이 runserver하기전에 wait_for_db라는 명령어를 만들어 줄거에요. 지금은 물론 없는 명령어기에 소스코드를 짜줘야해요.
python manage.py wait_for_db
python manage.py runserver
core/tests/test_commands.py
from unittest.mock import patch
from django.core.management import call_command # 명령어 입력시 소스코드 호출
from django.db.utils import OperationalError # django<-/->db 통신 안될때 뱉어내는 오류
from django.test import TestCase
class CommandTests(TestCase):
""" we create a command wait_for_db to check if database is
available before running server. Here we test if this command"""
# check if the command works when db is available
def test_wait_for_db_ready(self):
with patch('django.db.utils.ConnectionHandler.__getitem__') as gi:
gi.return_value = True
call_command('wait_for_db') # 콘솔창에 입력시 실행될 명령어
self.assertEqual(gi.call_count, 1)
# check if command works when db is not connected
# by default, we ll have sleep function to wait for 1s if database is not available
# we dont want this sleep to wait for this test
@patch('time.sleep', return_value=True)
def test_wait_for_db(self, ts):
with patch('django.db.utils.ConnectionHandler.__getitem__') as gi:
# make the patch return error for first five calls
# and return true on sixth call
gi.side_effect = [OperationalError]*5 + [True]
call_command('wait_for_db')
self.assertEqual(gi.call_count, 6)
@patch
데코레이터는 위에 작성된 with patch(~~~
소스코드와 동일한 결과를 도출하지만 작동방식이 달라요. 데코레이터의 경우 기생충같이 머리위에 달라붙었는데요. 함수의 인자 값으로 돌려주게되요. 근데 여기서는 사용하지 않지만 만약 넣지 않으면 unexpected arguments오류를 낼수 있어요.
gi 객체가 자신을 상대로 어떤 작업이 일어났는지 기억하는 점을 참고로 side_effect
발생시 오류를 발생시킵니다.
어쨋든 소스코드를 위와 같이 작성할게요. 그리고 테스트를 하게되면 Fail날거에요.
이를 해결하도록 해볼게요.