노마드 코더 Airbnb 클론 코딩

노마드 코더 에어비앤비 클론 코딩 #16 API TESTING

gogi masidda 2022. 12. 7. 16:59

API Testing: 우리 코드에서 발생할 수 있는 모든 케이스를 작성해놓고 명령어 하나로 테스트하는 것이다.

그 명령어인 'python manage.py test'를 입력하면, 파이썬은 내가 작성한 모든 테스트를 실행한다. 

 

APITestCase class 안에 있는 테스트 메소드 명명 규칙: 만약 django가 내 코드를 테스트해주기를 바란다면, 그 테스트 코드는 반드시 'test_'로 시작하는 메소드 안에 작성되어야 한다.

테스트 성공/ 실패

 

'self.client...'는 우리의 API로 get/post/put/delete request 등을 보낼 수 있게 해준다.

'python manage.py test'는 우리가 만들어둔 DB에서 일어나는게 아니라 새로운 DB를 만들어서 실행하고 테스트가 끝나면 새로 만들어진 DB는 삭제된다. 

테스트 실행시에 새로 만들어지는 DB는 'setUp' 메소드로 설정할 수 있다. setUp 메소드는 테스트들이 실행되기 전에 실행된다.

from rest_framework.test import APITestCase #rest_framework에서 사용되는 test case class
from . import models 
from users.models import User

class TestAmenities(APITestCase): #Amenities test

    NAME = "Amenity Test"
    DESC = "Amenity Description"
    URL = "/api/v1/rooms/amenities/"

    def setUp(self):
        models.Amenity.objects.create(name = self.NAME, description = self.DESC)


    def test_all_amenities(self): #get request test

        response = self.client.get(self.URL) #get request
        data = response.json()

        self.assertEqual(response.status_code, 200, "Status code isn't 200.") #누구나 response에 적힌 url을 접근할 수 있는지
        self.assertIsInstance(data, list) #list여야하는 data가 실제로 list인지
        self.assertEqual(len(data), 1)
        self.assertEqual(data[0]["name"], self.NAME)
        self.assertEqual(data[0]["description"], self.DESC)
    
    def test_create_amenity(self):

        new_amenity_name = "New Amenity"
        new_amenity_description = "New Amenity Description"

        response = self.client.post(self.URL, data={"name":new_amenity_name, "description":new_amenity_description}) #post request
        data = response.json()

        self.assertEqual(response.status_code, 200, "Status code isn't 200.") #post request시에 보낸 data가 유효한지
        self.assertEqual(data["name"], new_amenity_name)
        self.assertEqual(data["description"], new_amenity_description)

        response = self.client.post(self.URL) #데이터 없이 post request 실행
        data = response.json()

        self.assertEqual(response.status_code, 400) #그러면 Bad request 400이 뜸
        self.assertIn("name", data) # data에 필수 항목인 name이 있는지
        
class TestAmenity(APITestCase): #AmenityDetail test

    URL = "/api/v1/rooms/amenities/1" #어메니티의 pk 1.

    NAME = "Test Amenity"
    DESCRIPTION = "Test Amenity Description"

    def setUp(self):
        models.Amenity.objects.create(name = self.NAME, description = self.DESCRIPTION) #객체가 아무것도 없기 때문에 여기서 만들어지는 어메니티의 pk는 1임.

    def test_amenity_not_found(self):

        response = self.client.get("/api/v1/rooms/amenities/2") #get request. url로 이동했는데, 그 Amenity가 없을 때. 일부러 pk=2를 주고 에러가 발생하게.
        self.assertEqual(response.status_code, 404)

    def test_get_amenity(self): #get request test

        response = self.client.get(self.URL) # url로 이동했는데, 그 Ameniy가 존재할 때.
        self.assertEqual(response.status_code, 200)

        data = response.json()
        self.assertEqual(data["name"], self.NAME)
        self.assertEqual(data["description"], self.DESCRIPTION)

    def test_put_amenity(self):
		#put request에서는 필수항목이 없고 부분 수정이 가능하므로 필수 항목이었던 name이 있는지 체크할 필요가 없다.
        
        new_amenity_name = "New Amenity"
        new_amenity_description = "New Amenity Description"
        too_long_amenity_name = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"

        response = self.client.put(self.URL, data={"name":new_amenity_name, "description":new_amenity_description}) #put request
        data = response.json()
        self.assertEqual(response.status_code, 200, "Status code isn't 200.") #put request시에 보낸 data가 유효한지
        self.assertEqual(data["name"], new_amenity_name)
        self.assertEqual(data["description"], new_amenity_description)

        response = self.client.put(self.URL, data={"name":too_long_amenity_name})
        self.assertEqual(response.status_code, 400, "Too long Amenity name")


    def test_delete_amenity(self): #delete request

        response = self.client.delete(self.URL)
        self.assertEqual(response.status_code, 204)

 

Test Authentication: 테스트에서 인증 다루기

Rooms는 'permission_classes=[IsAuthenticatedOrReadOnly]'이기 때문에 GET은 인증 없이 아무나 할 수 있다. 하지만 POST는 인증이 있어야 사용 가능하다.

...
class TestRooms(APITestCase): #Rooms test

    def setUp(self):
        
        user =User.objects.create(username = "new user")
        user.set_password("123")
        user.save()
        self.user = user

    def test_create_room(self):

        response = self.client.post("/api/v1/rooms/") #post request
        self.assertEqual(response.status_code, 403) # 403 Forbidden. 인증없이 post를 하지 못하는지

        self.client.force_login(self.user) #인증을 하고 post request를 보냈을 때, 잘 동작하는지.
        response = self.client.post("/api/v1/rooms/") #post request
        print(response.json())

'force-login'은 user만 있어도 로그인 가능하다. username과 password는 없어도 된다.

 

이로써 에어비앤비 클론 코딩의 백엔드 부분은 끝이 났다. 다음은 프론트엔드 부분이다.

728x90