TDD (Test Driven Development) IN Django + 6

LEE EUI JOO·2023년 2월 6일
0

Web Programming

목록 보기
8/17

TDD - ' 기능이 먼저다 '

  • Test Driven Development 의 약자로 테스트 주도 개발로 번역
  • 개발에서 진행을 담당하는 주체를 테스트에 두는 방법

테스트 종류

  • Unit Test : 함수 단위(메서드) 단위로 테스트

  • 통합 테스트 : 함수들을 모아서 전체적으로 제대로 구동 되는지 테스트

  • 인수 테스트 : 개발 환경과 운영환경이 다른 경우 개발 환경에서 운영환경으로 이전할 때 수행

  • 블랙 박스 테스트 : 기능 테스트

  • 화이트 박스 테스트 : 구조 테스트

  • 알파 테스트 : 개발자의 장소에서 사용자가 테스트

  • 베타 테스트 : 사용자의 환경에서 사용자가 테스트


단위 테스트 프로세스

  • 구현하려는 기능에 대한 테스트 코드를 작성 - 모양만 생성

  • 테스트 실행 - 실패

  • 테스트를 통과할 수 있는 최소한의 기능을 구현

  • 테스트를 실행시키고 통과시키면 코드를 정리

  • 모든 기능을 구현할 때 까지 이를 반복


구현 과정 - MVC

Model ➔ Service ➔ Controller ➔ View

  • service 까지는 별도의 프로그램이 필요 없음

예) 도서 정보를 삽입하는 작업의 테스트

  • test.py 라는 파일에 테스트를 위한 테스트 코드를 작성

from django.test import TestCase
from .models import Book   #사실 에러
# Create your tests here.
class ModelTest(TestCase):
    # 테스트를 수행하기 전에 호출되는 함수
    def setup(self):
        self.book_title = 'harry poter'
        self.book_author= 'lee'
        self.book = Book(
            title=self.book_title, author = self.book_author)

        # 테스트를 위한 함수

    def test_model_can_create_a_bucketlist(self):
        old_count = Book.objects.count()
        self.book.save()
        new_count = Book.objects.count()
        self.assertNotEqual(old_count, new_count)

테스트 코드 실행 - 에러 발생

$ python manage.py test

  • Book 이 없기 때문에 에러가 발생했기 때문에 Book을 만들어 줘야한다!

모델 역할을 수행할 클래스 생성

  • models.py
from django.db import models

# Create your models here.
class Todo(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField(blank=True)
    created = models.DateTimeField(auto_now_add=True)
    complete = models.BooleanField(default=False)
    important = models.BooleanField(default=False)
    # 디버깅을 위해서 사용 - print로 인스턴스를 출력하면 호출되는 메서드

    def __str__(self):
        return self.title
        
#### Book 클래스
class Book(models.Model):
    title = models.CharField(max_length=128)
    author = models.CharField(max_length=128)

마이그레이션 실행

$ python manage.py makemigrations
$ python manage.py migrate


다시 TEST 실행

$ python manage.py test
  • 에러

  • test_todoapidb 는 mariadb terminal 상에는 보이지 않음
  • grant all privileges 명령어를 사용하여 해결!


다시 테스트

  • 에러 - 현재 애플리케이션에서는 /api/books/ 를 처리하는 로직이 없기 때문
  • 요청을 정상적으로 처리할 수 있도록 serializers 를 생성
from rest_framework import serializers
from .models import Todo

class TodoSimpleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Todo
        fields = ('id', 'title', 'complete','important')

class TodoCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Todo
        fields = ('title', 'description', 'complete','important')

class TodoDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = Todo
        fields = ('id', 'title', 'description', 'created', 'complete', 'important')

from.models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ('id','title','author')
  • views.py 파일에 삽입 요청을 처리할 로직을 생성
from rest_framework import status

from rest_framework.response import Response
from rest_framework.views import APIView

from .models import Todo

from .serializers import TodoSimpleSerializer, TodoCreateSerializer

class TodosAPIView(APIView):
    def get(self, request):
        todos = Todo.objects.filter(complete=False)
        serializer = TodoSimpleSerializer(todos, many=True)
        return Response(serializer.data,status=status.HTTP_200_OK)
    def post(self,request):
        # 파라미터를 가져와서 serializer를 생성
        serializer = TodoCreateSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status.HTTP_201_CREATED)
        return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)

from .serializers import TodoDetailSerializer
from rest_framework.generics import get_object_or_404
class TodoAPIView(APIView):
    def get(self, request, pk):
        # id 가 pk 인 데이터를 조회하고 없으면 404 에러 발생
        todo = get_object_or_404(Todo, id=pk)
        serializer = TodoDetailSerializer(todo)
        return Response(serializer.data,status=status.HTTP_200_OK)

    def put(self, request, pk):
        # id가 pk 인 데이터를 조회하고 없으면 404 에러 발생
        todo = get_object_or_404(Todo, id=pk)
        serializer = TodoCreateSerializer(todo, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)

#

class DoneTodosAPIView(APIView):
    def get(self, request):
        dones = Todo.objects.filter(complete=True)
        serializer = TodoSimpleSerializer(dones,many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

# 완료로 수정하기 위한 처리

class DoneTodoAPIView(APIView):
    def get(self, request, pk):
        done = get_object_or_404(Todo, id=pk)
        done.complete = True
        done.save()
        serializer = TodoDetailSerializer(done)
        return Response(serializer.data, status=status.HTTP_200_OK)

from .serializers import BookSerializer
from .models import Book
from rest_framework import generics

class CreateView(generics.CreateView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def perform_create(self,serializer):
        serializer.save()
  • urls.py 파일에 URL 처리를 생성
"""
from django.contrib import admin
from django.urls import path

from django.contrib import admin
from django.urls import path

from mytodoapp.views import TodosAPIView, TodoAPIView, DoneTodosAPIView, DoneTodoAPIView
from mytodoapp.views import CreateView
urlpatterns = [
    path('admin/', admin.site.urls),
    path('todo', TodosAPIView.as_view()),
    path('todo/<int:pk>',TodoAPIView.as_view()),
    path('done', DoneTodosAPIView.as_view()),
    path('done/<int:pk>',DoneTodoAPIView.as_view()),
    path('api/books/',CreateView.as_view())

]

  • 일반적으로는 Model에 필요한 모든 작업을 테스트 한 후 view로 넘어가는 방식이 있고 하나의 요청을 전부 테스트 한 다음 다른 요청으로 넘어가는 방식이 있다.
profile
무럭무럭 자라볼까

0개의 댓글