[TIL] # 34 Django Unittest

ddalkigum·2021년 1월 3일
1

TIL

목록 보기
33/50
post-thumbnail
post-custom-banner

Unit test진행

유닛테스트에서는 내가 현재 가지고 있는 데이터베이스가 아닌 별도의 테스트 데이터베이스가 생성된다

이 데이터 베이스는 테스트가 종료되면 삭제된다

client = Client()
class JustTest(TestCase):

    def setUp(self):
        print("--------------- setUp -----------------")
        user = User.objects.create(email = "jun@email.com", password = "wecode123")
        Post.objects.create(user = user, content = "고양이인가", image_url = "haha.jpg")

    def test_just_get_view(self):
        print("--------------- check_url -----------------")
        response = client.get("/posts")
        self.assertEqual(response.status_code, 200)
    
    def test_check_post(self):
        print("--------------- check_psot -----------------")
        post = Post.objects.get(id = 1)
        user = User.objects.get(id = 1)
        self.assertEqual(post.content, "고양이인가")

유저와 포스트를 만들고 테스트를 진행해 보는데

진행 순서를 보면 default 라는 db를 만들고
JustTest안의 메서드를 실행하게 되는데 setUp을 두번 실행합니다

메서드들이 다 진행된 후에는 default 데이터베이스를 삭제한다

궁금한점

  1. default 라는 이름이 DB가 있으면 어떻게 될까

  2. 왜 DB를 만들었다 지웟다 하지?

default 라는 이름의 DB가 있다면?

DEFAULT 라는 이름은 mysql에서 이미 사용중이 어서 default라는 이름의
데이터 베이스는 만들지 못햇습니다

CREATE DATABASE dbdb DEFAULT ----- 

DB를 만들었다 지웟다 하는지??

제가 생각한건 2가지 인데

  1. 테스트용 DB를 따로 만들어서 아예 테스트가 끝난후에 삭제를 하자

  2. 테스트용 DB가 아닌 내가 실제로 가지고 있는 DB로 테스트하면 안되나??

1번

우선 1번은 django에서 제공해주는 기능이 있습니다

python3 manage.py test --keepdb posts/   

이렇게 db를 유지를 해주게 되면 mysql에서 db가 추가된걸 확인할 수 있습니다

실제 mysql에서 데이터를 살펴보면 비어있는 걸 확인할 수 있습니다

데이터가 비어있는데 출력이 될까?

테스트상에서 데이터를 만들었다고 해도, 직접적으로 들어가지는 않습니다

그래서 비어있는데 만드는 부분을 지워도 출력이 될까 굼금했습니다

client = Client()
class JustTest(TestCase):

    #def setUp(self):
    #    print("--------------- setUp -----------------")
    #    user = User.objects.create(email = "jun@email.com", password = "wecode123")
    #    Post.objects.create(user = user, content = "고양이인가", image_url = "haha.jpg")

    def test_just_get_view(self):
        print("--------------- check_url -----------------")
        response = client.get("/posts")
        self.assertEqual(response.status_code, 200)
    
    def test_check_post(self):
        print("--------------- check_psot -----------------")
        post = Post.objects.get(id = 1)
        user = User.objects.get(id = 1)
        self.assertEqual(post.content, "고양이인가")

데이터 베이스를 Destroy 했던 부분이 Preserving으로 바뀌었습니다
데이터베이스를 유지시키지만 이상하게 실패가 나오네요

데이터를 만들었다 지우는건 똑같은 것 같아 보입니다
혹시나 데이터를 지웟다 없애면서 DELETE방식으로 지워지는 거라면
id값이 유지된 상태로 만들어 지니까 5번 테스트를 하고 나면 id가 5인 포스트가 만들어지는 건가
생각했는데 ... 맞습니다

이런식으로 진행이 됩니다

테스트


class JustTest(TestCase):

    def setUp(self):
       print("--------------- setUp -----------------")
       user = User.objects.create(email = "jun@email.com", password = "wecode123")
       Post.objects.create(user = user, content = "고양이인가", image_url = "haha.jpg")
    
    def test_check_post(self):
        print("--------------- check_psot -----------------")
        post = Post.objects.get(id = 3)
        self.assertEqual(post.content, "고양이인가")

테스트는 이 코드를 가지고 진행했고

3번째 진행될때 ok 나 나오는 걸 확인할 수 있습니다

이런점을 보면 데이터베이스를 유지 하는게 유리한가?? 의문입니다

문제점

테스트를 실행 할때마다 --keepdb를 적어주지 않으면
DB가 존재하는데 삭제할거냐고 물어봅니다

뭐.. 한두번 테스트하는 경우에는 적어주면서 하면 괜찮겠지만,
테스트를 계속 진행하는데 있어서 이부분은 굉장히 불편할 것 같습니다

2번

사실 2번을 사용하게 되면 테스트를 하는데에 의미가 없다고 생각해서
찾아보다가 DB를 없이 테스트를 진행하는 방법을 봐서 이 방법을 알아봤습니다

3번 DB없이 테스트 진행

우선 테스트 DB를 없애주고

settings파일이 있는 디렉토리에

setttings_test.py 와 test_runner.py 두개의 파일을 생성합니다

매번 생성했다 지웠다 하는것은 비효율적이지 않을까 생각이 들었고,
DB가 없다면 어떻게 이 데이터를 가지고 오는거지? 생각했습니다

test_runner.py 에서는 장고의 유닛테스트에서 사용되는 runner를 재정의 해줍니다

이 두가지 메서드를 오버라이드 해주어서 디비생성과 삭제하는 과정을 없애주는 것입니다

def setup_databases(self, **kwargs):
        return _setup_databases(
            self.verbosity, self.interactive, self.keepdb, self.debug_sql,
            self.parallel, **kwargs
        )

def teardown_databases(self, old_config, **kwargs):
        """Destroy all the non-mirror databases."""
        _teardown_databases(
            old_config,
            verbosity=self.verbosity,
            parallel=self.parallel,
            keepdb=self.keepdb,
        )

변경후

# test_runner.py
from django.test.runner import DiscoverRunner

class TestRunner(DiscoverRunner):
    
    def setup_databases(self, **kwargs):
        pass
    
    def teardown_databases(self, old_config, **kwargs):
        pass

DiscoverRunner가 디비를 생성을 담당하는 클래스 이고, 이렇게 과정을 없애줌으로써
테스트 DB생성 없이 테스트가 가능해집니다

manage.py test 에서 사용하는 커맨드들을 확인할 수 있고

여기에는 아까 사용햇엇던 keepdb 명령어도 보입니다

settings_test.py에서는 test_runner에서 정의한 TestRunner 클래스를
테스트 러너로 지정하는 파일입니다

이렇게 DB를 생성하지 않고 테스트를 하는 과정은 실제 내가 사용하고 있는 DB에서 이루어 지며
테스트상에서 create를 하더라도 실제로 생성이 이루어지지는 않습니다

class JustTest(TestCase):

    def setUp(self):
       print("--------------- setUp -----------------")
       user = User.objects.create(email = "jun@email.com", password = "wecode123")
       Post.objects.create(user = user, content = "고양이인가", image_url = "haha.jpg")
    
    def test_check_post(self):
        print("--------------- check_psot -----------------")
        post = Post.objects.get(id = 4)
        self.assertEqual(post.content, "고양이인가")

몇번을 테스트 해봤는데 DB에서 생성은 없었고
찾아오는 부분이 실제 DB를 통해 테스트를 진행하는 걸 확인할 수 있었습니다


참고한 곳

DB없이 테스트 진행
https://blueshw.github.io/2016/03/06/django-unit-test-without-testdb/

profile
딸기검 -본캐🐒 , 김준형 - 현실 본캐 🐒
post-custom-banner

0개의 댓글