아래의 유닛테스트 코드를 만들기위해
내가 product의 상세페이지의 정보를 get하는 로직을 구현중에 있었기 때문에
당연히 해당 로직에 대한 유닛테스트를 작성할때도 product에 대한 테이블을 create를 했더니 해당 product가 참조 하고 있는 것을 알수가 없다는 에러를 발견함
위의 문제를 해결하기 위해선,
product가 참조하고 있는 관계의 테이블도 모두 create를 통해 목데이터를 생성해주면 된다
A : 그래서, product는 subcategory를 참조하고 있고
subcategory는 category를 참조하고 있고
category는 menu를 참조하고 있다.
==> 얻은 교훈 : 유닛 테스트를 위한 목데이터를 생성할땐,
많은 데이터까지 필요없고,
작성한 로직을 표현할 수 있는 만큼의 데이터를 생성하면 될듯...3~4개 정도도 오케이
그리고 내가 만든 로직이 테이블이 참조하고 있는 관계성이 있다면
정보가 어떻게 불어와지는지 그 관계성과 그관계성 사이의 foreinkey를 고려해서 생성순서를 작성해주면 좋음
(아래서 잘못작성한게, 먼저 menu -> categorgy -> subcategory -> product -> image 순서대로 작성하지 않은것이다.
서로 foreinkey의 관계를 잘 파악하도록 하자!!)
import json
from django.http import response
from django.test import TestCase, Client
from products.models import Category, Image, Menu, Product, SubCategory
class ProductDetailTest(TestCase):
def setUp(self):
self.client = Client()
Menu.objects.create(
name = '홈'
)
Category.objects.create(
name = '옷',
menu = 1
)
SubCategory.objects.create(
name = '상의',
Category = 1
)
Image.objects.create(
image_url = 'http:상품1이미지',
product = 1
)
# Image.objects.create(
# image_url = 'http:상품1이미지',
# product = 1
# )
Image.objects.create(
image_url = 'http:상품2이미지',
product = 2
)
Image.objects.create(
image_url = 'http:상품3이미지',
product = 3
)
Image.objects.create(
image_url = 'http:상품4이미지',
product = 4
)
Product.objects.create(
id = 1,
name = '상품1',
price = 1111111,
brand = 'zara',
description = '상품1설명입니다',
thumbnail_image_url = 'http:상품1썸네일이미지'
)
Product.objects.create(
id = 2,
name = '상품2',
price = 222222,
brand = 'zara2',
description = '상품2설명입니다',
thumbnail_image_url = 'http:상품2썸네일이미지'
)
Product.objects.create(
id = 3,
name = '상품3',
price = 333333,
brand = 'zara3',
description = '상품3설명입니다',
thumbnail_image_url = 'http:상품3썸네일이미지'
)
Product.objects.create(
id = 4,
name = '상품4',
price = 444444,
brand = 'zara4',
description = '상품4설명입니다',
thumbnail_image_url = 'http:상품4썸네일이미지'
)
def tearDown(self):
Product.objects.all().delete()
def test_productdetailview_get_success(self):
client = Client()
# result = {
# 'name' : '상품1',
# 'price' : 1111111,
# 'brand' : 'zara',
# 'description' : '상품1설명입니다',
# 'thumbnail_image_url' : 'http:상품1썸네일이미지',
# 'image_url' : 'http:상품1이미지'
# }
response = client.get('/product/1')
self.assertEqual(response.json(),
{
"messagee" : {
'name' : '상품1',
'price' : 1111111,
'brand' : 'zara',
'description' : '상품1설명입니다',
'thumbnail_image_url' : 'http:상품1썸네일이미지',
'image_url' : 'http:상품1이미지'
}
# "result" : [
# {'message':1},
# {'message':2},
# {'message':3},
# {'message':4},
# {'message':5}
# ],
}
)
self.assertEqual(response.status_code, 200)
Q : 위의 코드에서도 에러 발생--> image의 forginkey가 없다고..?
그런 에러 발생
A : 이미지가 참조하고 있는 것은 product인데 Image라는 class를 create 하는데 참조하는 prodcut를 먼저 create 하지를 않았는데
image를 만들때 필요한 요소인 image_url과 product_id를 주지 만들어주지 않음....해당 에러를 해결하기 위해 product를 먼저 create를 해주고 나서 image를 create 해주면 참조하고 있는 관계성이 맞아 떨어짐..
프러덕트 아이디1번에 물린 이미지 2개중 테스트 할 당시에 이미지 1개만 넘겨줫을때 발생하 에러
import json
from django.http import response
from django.test import TestCase, Client
from products.models import Category, Image, Menu, Product, SubCategory
class ProductDetailTest(TestCase):
def setUp(self):
self.client = Client()
Menu.objects.create(
name = '홈'
)
Category.objects.create(
name = '옷',
menu_id = 1
)
SubCategory.objects.create(
name = '상의',
category_id = 1
)
Product.objects.create(
id = 1,
name = '상품1',
price = '1111111.00',
brand = 'zara',
description = '상품1설명입니다',
thumbnail_image_url = 'http:상품1썸네일이미지',
sub_category_id = 1
)
Product.objects.create(
name = '상품2',
price = '222222.00',
brand = 'zara2',
description = '상품2설명입니다',
thumbnail_image_url = 'http:상품2썸네일이미지',
sub_category_id = 1
)
Product.objects.create(
id = 3,
name = '상품3',
price = '333333.00',
brand = 'zara3',
description = '상품3설명입니다',
thumbnail_image_url = 'http:상품3썸네일이미지',
sub_category_id = 1
)
Product.objects.create(
id = 4,
name = '상품4',
price = '444444.00',
brand = 'zara4',
description = '상품4설명입니다',
thumbnail_image_url = 'http:상품4썸네일이미지',
sub_category_id = 1
)
Image.objects.create(
image_url = 'http:상품1이미지',
product_id = 1
)
Image.objects.create(
image_url = 'http:상품5이미지',
product_id = 1
)
Image.objects.create(
image_url = 'http:상품2이미지',
product_id = 2
)
Image.objects.create(
image_url = 'http:상품3이미지',
product_id = 3
)
Image.objects.create(
image_url = 'http:상품4이미지',
product_id = 4
)
def tearDown(self):
Product.objects.all().delete()
def test_productdetailview_get_success(self):
client = Client()
response = client.get('/product/1')
self.assertEqual(response.json(),
{
"message" : {
'name' : '상품1',
'price' : '1111111.00',
'brand' : 'zara',
'description' : '상품1설명입니다',
'thumbnail_image_url' : 'http:상품1썸네일이미지',
'image_url' : ['http:상품1이미지']
}
}
)
self.assertEqual(response.status_code, 200)
def test_productdetailview_get_success(self):
client = Client() #--> 이부분은 다시 이해해야함
response = client.get('/product/1') #--> url이 product
self.assertEqual(response.json(),
{
"message" : {
'name' : '상품1',
'price' : '1111111.00',
'brand' : 'zara',
'description' : '상품1설명입니다',
'thumbnail_image_url' : 'http:상품1썸네일이미지',
'image_url' : ['http:상품1이미지', 'http:상품5이미지']
}
}
)
self.assertEqual(response.status_code, 200)
물품_id가 5번의 목데이터를 Productg.objects.create()를 안해서 생성이 안됨
create 되지 않은 상품을 불러왓을때 에러가 doesnotexist가 발생하게 코드를 작성하였고
실제로 있는 4번과 없는 5번에 경우로 확인 가능
어제 작성한 부분이 제대로 작성되고 잇는지 확인하기 위해
도중도중 print로 확인을 해보았다.
class ProductDetailTest(TestCase):
def setUp(self):
self.client = Client()
Menu.objects.create(
name = '홈'
)
print(1)
Category.objects.create(
name = '옷',
menu_id = 1
)
print(2)
SubCategory.objects.create(
name = '상의',
category_id = 1
)
print(3)
Product.objects.create(
id = 1,
name = '상품1',
price = '1111111.00',
brand = 'zara',
description = '상품1설명입니다',
thumbnail_image_url = 'http:상품1썸네일이미지',
sub_category_id = 1
)
print(4)
Product.objects.create(
id = 2,
name = '상품2',
price = '222222.00',
brand = 'zara2',
description = '상품2설명입니다',
thumbnail_image_url = 'http:상품2썸네일이미지',
sub_category_id = 1
)
print(5)
Product.objects.create(
id = 3,
name = '상품3',
price = '333333.00',
brand = 'zara3',
description = '상품3설명입니다',
thumbnail_image_url = 'http:상품3썸네일이미지',
sub_category_id = 1
)
print(6)
Product.objects.create(
id = 4,
name = '상품4',
price = '444444.00',
brand = 'zara4',
description = '상품4설명입니다',
thumbnail_image_url = 'http:상품4썸네일이미지',
sub_category_id = 1
)
print(7)
Image.objects.create(
image_url = 'http:상품1이미지',
product_id = 1
)
print(8)
Image.objects.create(
image_url = 'http:상품5이미지',
product_id = 1
)
print(9)
Image.objects.create(
image_url = 'http:상품2이미지',
product_id = 2
)
print(10)
Image.objects.create(
image_url = 'http:상품3이미지',
product_id = 3
)
print(11)
Image.objects.create(
image_url = 'http:상품4이미지',
product_id = 4
)
print(12)
def tearDown(self):
Menu.objects.all().delete()
SubCategory.objects.all().delete()
Category.objects.all().delete()
Product.objects.all().delete()
Image.objects.all().delete()
print(13)
def test_product_detail_view_get_success(self):
client = Client()
response = client.get('/products/1')
self.assertEqual(response.json(),
{
'message' : {
'name' : '상품1',
'price' : '1111111.00',
'brand' : 'zara',
'description' : '상품1설명입니다',
'thumbnail_image_url' : 'http:상품1썸네일이미지',
'image_url' : ['http:상품1이미지', 'http:상품5이미지']
}
}
)
self.assertEqual(response.status_code, 200)
print(14)
def test_product_detail_view_get_doesnotexist(self):
client = Client()
response = client.get('/products/5')
self.assertEqual(response.json(),
{'message': 'PRODUCT_DOESNOT_EXIST'}
)
self.assertEqual(response.status_code, 400)
print(15)
역시나
forien key 관한 에러가 발생했다
보여지는 1~13까지 숫자는 내가 위에서 print
를 작성한 흔적이다.
내가 유닛테스트를 작성한 순서대로 도중에 오류없이 작성된 순서대로 print(13) 부분까지 작성되었음을 알 수있다.
그러나 그대로 에러가 발생했다
....뭐가 문제라는 걸까...?
내가 작성한 유닛테스트 코드에서 create를 통해서 데이터를 생성할때
Product에 대한 데이터를 생성할때만
id값 코드를 작성하고 다른 Menu, SubCategory, Category, Image를 데이터를 생성할때 id값 코드를 작성하지 않았다...
여기서 발생한 문제점은 발견했다.
그 문제점이란?
위에서 언급한 id값 코드를 작성하지 않은 부분들에 id 값이 create를 할때 자동으로 고유값을 생성해줄 것이라고 생각했기 때문에 작성하지 않았는데 저 id값들을 작성해주고 나서 test를 돌려보니
감쪽같이 발생했던 에러가 사라지고 ok가 발생했다....
그래서 원인은 해결햇지만....
이유를 모를뿐...
그 이유는 구글링을 좀더 하던가...멘토님께 도움의 손길을 얻으려고 한다.
저 문제를 발견한건 목요일이였고...금요일은 우선은 유닛테스트 작성하는거에 목적을 두다가...
결국 저 이유를 토욜아침부터 멘토께 달려가서 이유를 들었다..햐하하 죄송합니다...ㅎㅎㅎ
자, 멘토님의 도움의 손길을 얻어 이유를 알았다...하..잼잇어...
유닛테스트를 시행할때 목데이터를 create하고 테스트1번 함수를 시행하고 delete하고 다시 create하고 테스트2번 함수 시행하고 delete하고..이걸 테스트 할때마다 생성 -> 테스트함수실행 -> 삭제 -> 생성 -> 테스트함수실행 -> 삭제 순서로 진행순서때문이라고 한다
내가 Product에서만 id값을 설정하고 나머지 Menu, SubCategory, Category, Image를 생성할때는 id값을 설정해주지 않았다
delete를 하고 새로운 오브젝트를 create할때 삭제되엇던 id값의 데이터는 없지만 삭제후 생성된 id값은 순서가 밀림을 db에서 확인해본적이 있을것이다
그 원리가 동일하게 적용된다고 볼수잇따
유닛테스트를 진행할때 id값을 지정해줌으로써 강제적으로 그 id값을 설정해주는 것이다
내가 forienkey를 물고있는 SubCategory, Category, Product, Image들이 참조하고있는 _id값은 동일한데 유닛텍스트를 진행하면서 고유의 id값을 찾을수 없다고 해당 forienkey를 알수없다고 떳던 것이다...ㅠㅠㅠ
이유를 알아서 너무 좋음 ㅠㅜㅠㅠ
내가 왜 product를 생성할때만 id값을 작성햇는진 모르겟지만 원인과 그 이유를 알아서 넘나 즐겁군^^