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는 없어도 된다.
이로써 에어비앤비 클론 코딩의 백엔드 부분은 끝이 났다. 다음은 프론트엔드 부분이다.
'노마드 코더 Airbnb 클론 코딩' 카테고리의 다른 글
노마드 코더 에어비앤비 클론 코딩 #15 AUTHENTICATION (0) | 2022.12.01 |
---|---|
노마드 코더 에어비앤비 클론 코딩 #12 USERS API (0) | 2022.11.23 |
노마드 코더 에어비앤비 클론 코딩 #11 Rest API - 2 (1) | 2022.11.19 |
노마드 코더 에어비앤비 클론 코딩 #11 Rest API - 1 (0) | 2022.11.08 |
노마드 코더 에어비앤비 클론 코딩 #10 Django Rest Framework (1) | 2022.11.05 |