์ฅ๊ณ (Django)์ ํ ์คํธ ํ๋ ์์ํฌ์ ๋ํ ์ฌ์ธต ๋ถ์. TestCase์ TransactionTestCase๋ฅผ ๋น๊ต ๋์กฐํ์ฌ ๋ ํจ๊ณผ์ ์ด๊ณ ์ ๋ขฐํ ์ ์๋ ํ ์คํธ๋ฅผ ์์ฑํ ์ ์๋๋ก ๋์ต๋๋ค.
ํ์ด์ฌ ์ฅ๊ณ (Django) ํ ์คํ : TestCase์ TransactionTestCase์ ๋น๊ต
ํ
์คํ
์ ์ํํธ์จ์ด ๊ฐ๋ฐ์ ํต์ฌ์ ์ธ ๋ถ๋ถ์ผ๋ก, ์ ํ๋ฆฌ์ผ์ด์
์ด ์์๋๋ก ๋์ํ๊ณ ์๊ฐ์ด ์ง๋๋ ์์ ์ ์ผ๋ก ์ ์ง๋๋๋ก ๋ณด์ฅํฉ๋๋ค. ์ธ๊ธฐ ์๋ ํ์ด์ฌ ์น ํ๋ ์์ํฌ์ธ ์ฅ๊ณ (Django)๋ ํจ๊ณผ์ ์ธ ํ
์คํธ๋ฅผ ์์ฑํ๋ ๋ฐ ๋์์ด ๋๋ ๊ฐ๋ ฅํ ํ
์คํ
ํ๋ ์์ํฌ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์์๋ ์ฅ๊ณ ํ
์คํ
ํ๋ ์์ํฌ์ ๋ ๊ฐ์ง ๊ธฐ๋ณธ ํด๋์ค์ธ TestCase
์ TransactionTestCase
์ ๋ํด ์์ธํ ์์๋ณด๊ฒ ์ต๋๋ค. ๋ ํด๋์ค์ ์ฐจ์ด์ , ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์ดํด๋ณด๊ณ , ํ
์คํธ ์๊ตฌ์ ๋ง๋ ์ ์ ํ ํด๋์ค๋ฅผ ์ ํํ๋ ๋ฐ ๋์์ด ๋๋ ์ค์ ์์ ๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ฅ๊ณ (Django)์์ ํ ์คํ ์ด ์ค์ํ ์ด์
TestCase
์ TransactionTestCase
์ ์ธ๋ถ ์ฌํญ์ ์ดํด๋ณด๊ธฐ ์ ์, ์ฅ๊ณ ๊ฐ๋ฐ์์ ํ
์คํ
์ด ์ ๊ทธํ ๋ก ์ค์ํ์ง ๊ฐ๋ตํ๊ฒ ๋
ผ์ํด ๋ณด๊ฒ ์ต๋๋ค:
- ์ฝ๋ ํ์ง ๋ณด์ฅ: ํ ์คํธ๋ ๊ฐ๋ฐ ๊ณผ์ ์ด๊ธฐ์ ๋ฒ๊ทธ๋ฅผ ๋ฐ๊ฒฌํ์ฌ ํ๋ก๋์ ํ๊ฒฝ์ผ๋ก ์ ์ ๋๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค.
- ๋ฆฌํฉํ ๋ง ์ฉ์ด์ฑ: ํฌ๊ด์ ์ธ ํ ์คํธ ์ค์ํธ๊ฐ ์์ผ๋ฉด, ํ ์คํธ๊ฐ ํ๊ท(regression) ๋ฐ์ ์ ์๋ ค์ค ๊ฒ์ด๋ผ๋ ํ์ ์ ๊ฐ์ง๊ณ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํ ์ ์์ต๋๋ค.
- ํ์ ๊ฐ์ : ์ ์์ฑ๋ ํ ์คํธ๋ ์ฝ๋์ ๋ํ ๋ฌธ์ ์ญํ ์ ํ์ฌ ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค์ด ์ฝ๋๋ฅผ ์ดํดํ๊ณ ๊ธฐ์ฌํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
- ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ(TDD) ์ง์: TDD๋ ์ค์ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ ์ ํ ์คํธ๋ฅผ ๋จผ์ ์์ฑํ๋ ๊ฐ๋ฐ ์ ๊ทผ ๋ฐฉ์์ ๋๋ค. ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ๋ ๋์์ ๋ํด ๋ฏธ๋ฆฌ ์๊ฐํ๊ฒ ํ์ฌ ๋ ๊นจ๋ํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์ด ์ฝ๋๋ฅผ ๋ง๋ญ๋๋ค.
์ฅ๊ณ (Django)์ ํ ์คํ ํ๋ ์์ํฌ: ๊ฐ๋ตํ ๊ฐ์
์ฅ๊ณ ์ ํ
์คํ
ํ๋ ์์ํฌ๋ ํ์ด์ฌ์ ๋ด์ฅ unittest
๋ชจ๋์ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค. ์ด๋ ๋ค์๊ณผ ๊ฐ์ ์ฅ๊ณ ์ ํ๋ฆฌ์ผ์ด์
ํ
์คํธ๋ฅผ ๋ ์ฝ๊ฒ ๋ง๋๋ ์ฌ๋ฌ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค:
- ํ ์คํธ ๋ฐ๊ฒฌ: ์ฅ๊ณ ๋ ํ๋ก์ ํธ ๋ด์ ํ ์คํธ๋ฅผ ์๋์ผ๋ก ๋ฐ๊ฒฌํ๊ณ ์คํํฉ๋๋ค.
- ํ ์คํธ ์คํ๊ธฐ: ์ฅ๊ณ ๋ ํ ์คํธ๋ฅผ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ๋ ํ ์คํธ ์คํ๊ธฐ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ๋จ์ธ(Assertion) ๋ฉ์๋: ์ฅ๊ณ ๋ ์ฝ๋์ ์์ ๋์์ ๊ฒ์ฆํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ๋ค์ํ ๋จ์ธ ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ํด๋ผ์ด์ธํธ: ์ฅ๊ณ ์ ํ ์คํธ ํด๋ผ์ด์ธํธ๋ฅผ ์ฌ์ฉํ๋ฉด ํผ ์ ์ถ์ด๋ API ์์ฒญ๊ณผ ๊ฐ์ ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ์ ์ฌ์ฉ์ ์ํธ์์ฉ์ ์๋ฎฌ๋ ์ด์ ํ ์ ์์ต๋๋ค.
- TestCase์ TransactionTestCase: ์ด๋ค์ ์ฅ๊ณ ์์ ํ ์คํธ๋ฅผ ์์ฑํ๊ธฐ ์ํ ๋ ๊ฐ์ง ๊ธฐ๋ณธ ํด๋์ค์ด๋ฉฐ, ์์ธํ ์ดํด๋ณผ ๊ฒ์ ๋๋ค.
TestCase: ๋น ๋ฅด๊ณ ํจ์จ์ ์ธ ๋จ์ ํ ์คํธ
TestCase
๋ ์ฅ๊ณ ์์ ๋จ์ ํ
์คํธ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์ฃผ์ ํด๋์ค์
๋๋ค. ๊ฐ ํ
์คํธ ์ผ์ด์ค์ ๋ํด ๊นจ๋ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ๊ฒฝ์ ์ ๊ณตํ์ฌ ํ
์คํธ๊ฐ ์๋ก ๊ฒฉ๋ฆฌ๋๊ณ ๊ฐ์ญํ์ง ์๋๋ก ๋ณด์ฅํฉ๋๋ค.
TestCase์ ์๋ ๋ฐฉ์
TestCase
๋ฅผ ์ฌ์ฉํ๋ฉด, ์ฅ๊ณ ๋ ๊ฐ ํ
์คํธ ๋ฉ์๋์ ๋ํด ๋ค์ ๋จ๊ณ๋ฅผ ์ํํฉ๋๋ค:
- ํ ์คํธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ฑ: ์ฅ๊ณ ๋ ๊ฐ ํ ์คํธ ์คํ๋ง๋ค ๋ณ๋์ ํ ์คํธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์์ฑํฉ๋๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ๋ฌ์: ๊ฐ ํ ์คํธ ๋ฉ์๋ ์ ์, ์ฅ๊ณ ๋ ํ ์คํธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํ๋ฌ์ํ์ฌ ๊ธฐ์กด์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
- ํ ์คํธ ๋ฉ์๋ ์คํ: ์ฅ๊ณ ๋ ์ ์ํ ํ ์คํธ ๋ฉ์๋๋ฅผ ์คํํฉ๋๋ค.
- ํธ๋์ญ์ ๋กค๋ฐฑ: ๊ฐ ํ ์คํธ ๋ฉ์๋ ํ์, ์ฅ๊ณ ๋ ํธ๋์ญ์ ์ ๋กค๋ฐฑํ์ฌ ํ ์คํธ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐํด์ง ๋ชจ๋ ๋ณ๊ฒฝ ์ฌํญ์ ํจ๊ณผ์ ์ผ๋ก ์ทจ์ํฉ๋๋ค.
์ด ์ ๊ทผ ๋ฐฉ์์ ๊ฐ ํ
์คํธ ๋ฉ์๋๊ฐ ๊นจ๋ํ ์ํ์์ ์์ํ๋๋ก ๋ณด์ฅํ๋ฉฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐํด์ง ๋ชจ๋ ๋ณ๊ฒฝ ์ฌํญ์ด ์๋์ผ๋ก ๋ณต๊ตฌ๋ฉ๋๋ค. ์ด๋ก ์ธํด TestCase
๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ณ ๊ตฌ์ฑ ์์๋ฅผ ๊ฒฉ๋ฆฌํ์ฌ ํ
์คํธํ๋ ค๋ ๋จ์ ํ
์คํธ์ ์ด์์ ์
๋๋ค.
์์ : ๊ฐ๋จํ ๋ชจ๋ธ ํ ์คํธํ๊ธฐ
TestCase
๋ฅผ ์ฌ์ฉํ์ฌ ์ฅ๊ณ ๋ชจ๋ธ์ ํ
์คํธํ๋ ๊ฐ๋จํ ์์ ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค:
from django.test import TestCase
from .models import Product
class ProductModelTest(TestCase):
def test_product_creation(self):
product = Product.objects.create(name="Test Product", price=10.00)
self.assertEqual(product.name, "Test Product")
self.assertEqual(product.price, 10.00)
self.assertTrue(isinstance(product, Product))
์ด ์์ ์์๋ Product
๋ชจ๋ธ ์ธ์คํด์ค์ ์์ฑ์ ํ
์คํธํฉ๋๋ค. test_product_creation
๋ฉ์๋๋ ์ ์ ํ์ ์์ฑํ ๋ค์, ๋จ์ธ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ์ ์์ฑ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์ค์ ๋์๋์ง ํ์ธํฉ๋๋ค.
TestCase ์ฌ์ฉ ์๊ธฐ
TestCase
๋ ๋๋ถ๋ถ์ ์ฅ๊ณ ํ
์คํธ ์๋๋ฆฌ์ค์์ ์ผ๋ฐ์ ์ผ๋ก ์ ํธ๋๋ ์ ํ์
๋๋ค. ๋น ๋ฅด๊ณ ํจ์จ์ ์ด๋ฉฐ, ๊ฐ ํ
์คํธ์ ๋ํด ๊นจ๋ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ๊ฒฝ์ ์ ๊ณตํฉ๋๋ค. ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์ TestCase
๋ฅผ ์ฌ์ฉํ์ธ์:
- ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ณ ๋ชจ๋ธ, ๋ทฐ ๋๋ ๊ธฐํ ๊ตฌ์ฑ ์์๋ฅผ ํ ์คํธํ ๋.
- ํ ์คํธ๊ฐ ์๋ก ๊ฒฉ๋ฆฌ๋๊ณ ๊ฐ์ญํ์ง ์๋๋ก ๋ณด์ฅํ๊ณ ์ถ์ ๋.
- ์ฌ๋ฌ ํธ๋์ญ์ ์ ๊ฑธ์น ๋ณต์กํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ์์ฉ์ ํ ์คํธํ ํ์๊ฐ ์์ ๋.
TransactionTestCase: ๋ณต์กํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ์์ฉ ํ ์คํธ
TransactionTestCase
๋ ์ฅ๊ณ ์์ ํ
์คํธ๋ฅผ ์์ฑํ๊ธฐ ์ํ ๋ ๋ค๋ฅธ ํด๋์ค์ด์ง๋ง, ๋ฐ์ดํฐ๋ฒ ์ด์ค ํธ๋์ญ์
์ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์์ TestCase
์ ๋ค๋ฆ
๋๋ค. ๊ฐ ํ
์คํธ ๋ฉ์๋ ํ์ ํธ๋์ญ์
์ ๋กค๋ฐฑํ๋ ๋์ , TransactionTestCase
๋ ํธ๋์ญ์
์ ์ปค๋ฐํฉ๋๋ค. ์ด๋ก ์ธํด ์๊ทธ๋์ด๋ ์์์ ํธ๋์ญ์
(atomic transactions)๊ณผ ๊ฐ์ด ์ฌ๋ฌ ํธ๋์ญ์
์ ๊ฑธ์น ๋ณต์กํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ์์ฉ์ ํ
์คํธํ๋ ๋ฐ ์ ํฉํฉ๋๋ค.
TransactionTestCase์ ์๋ ๋ฐฉ์
TransactionTestCase
๋ฅผ ์ฌ์ฉํ๋ฉด, ์ฅ๊ณ ๋ ๊ฐ ํ
์คํธ ์ผ์ด์ค์ ๋ํด ๋ค์ ๋จ๊ณ๋ฅผ ์ํํฉ๋๋ค:
- ํ ์คํธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ฑ: ์ฅ๊ณ ๋ ๊ฐ ํ ์คํธ ์คํ๋ง๋ค ๋ณ๋์ ํ ์คํธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์์ฑํฉ๋๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํ๋ฌ์ํ์ง ์์: TransactionTestCase๋ ๊ฐ ํ ์คํธ ์ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์๋์ผ๋ก ํ๋ฌ์ํ์ง *์์ต๋๋ค*. ๊ฐ ํ ์คํธ๊ฐ ์คํ๋๊ธฐ ์ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ผ๊ด๋ ์ํ์ ์์ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค.
- ํ ์คํธ ๋ฉ์๋ ์คํ: ์ฅ๊ณ ๋ ์ ์ํ ํ ์คํธ ๋ฉ์๋๋ฅผ ์คํํฉ๋๋ค.
- ํธ๋์ญ์ ์ปค๋ฐ: ๊ฐ ํ ์คํธ ๋ฉ์๋ ํ์, ์ฅ๊ณ ๋ ํธ๋์ญ์ ์ ์ปค๋ฐํ์ฌ ํ ์คํธ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ณ๊ฒฝ ์ฌํญ์ ์๊ตฌ์ ์ผ๋ก ๋ง๋ญ๋๋ค.
- ํ ์ด๋ธ ์ด๊ธฐํ(Truncate): TransactionTestCase์ ๋ชจ๋ ํ ์คํธ๊ฐ *๋๋๋ฉด*, ๋ฐ์ดํฐ๋ฅผ ์ง์ฐ๊ธฐ ์ํด ํ ์ด๋ธ์ด ์ด๊ธฐํ(truncate)๋ฉ๋๋ค.
TransactionTestCase
๋ ๊ฐ ํ
์คํธ ๋ฉ์๋ ํ์ ํธ๋์ญ์
์ ์ปค๋ฐํ๊ธฐ ๋๋ฌธ์, ํ
์คํธ๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ผ๊ด์ฑ ์๋ ์ํ๋ก ๋จ๊ฒจ๋์ง ์๋๋ก ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ํ์ ํ
์คํธ์ ์ํฅ์ ์ฃผ์ง ์๋๋ก ํ
์คํธ ์ค์ ์์ฑ๋ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก ์ ๋ฆฌํด์ผ ํ ์๋ ์์ต๋๋ค.
์์ : ์๊ทธ๋ ํ ์คํธํ๊ธฐ
TransactionTestCase
๋ฅผ ์ฌ์ฉํ์ฌ ์ฅ๊ณ ์๊ทธ๋์ ํ
์คํธํ๋ ์์ ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค:
from django.test import TransactionTestCase
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Product, ProductLog
@receiver(post_save, sender=Product)
def create_product_log(sender, instance, created, **kwargs):
if created:
ProductLog.objects.create(product=instance, action="Created")
class ProductSignalTest(TransactionTestCase):
def test_product_creation_signal(self):
product = Product.objects.create(name="Test Product", price=10.00)
self.assertEqual(ProductLog.objects.count(), 1)
self.assertEqual(ProductLog.objects.first().product, product)
self.assertEqual(ProductLog.objects.first().action, "Created")
์ด ์์ ์์๋ ์๋ก์ด Product
์ธ์คํด์ค๊ฐ ์์ฑ๋ ๋๋ง๋ค ProductLog
์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ์๊ทธ๋์ ํ
์คํธํฉ๋๋ค. test_product_creation_signal
๋ฉ์๋๋ ์ ์ ํ์ ์์ฑํ ๋ค์, ํด๋น ์ ํ ๋ก๊ทธ ํญ๋ชฉ์ด ์์ฑ๋์๋์ง ํ์ธํฉ๋๋ค.
TransactionTestCase ์ฌ์ฉ ์๊ธฐ
TransactionTestCase
๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ๋ฌ ํธ๋์ญ์
์ ๊ฑธ์น ๋ณต์กํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ์์ฉ์ ํ
์คํธํด์ผ ํ๋ ํน์ ์๋๋ฆฌ์ค์์ ์ฌ์ฉ๋ฉ๋๋ค. ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์ TransactionTestCase
์ฌ์ฉ์ ๊ณ ๋ คํ์ธ์:
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ์ํด ํธ๋ฆฌ๊ฑฐ๋๋ ์๊ทธ๋์ ํ ์คํธํ ๋.
- ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ํฌํจํ๋ ์์์ ํธ๋์ญ์ (atomic transactions)์ ํ ์คํธํ ๋.
- ์ผ๋ จ์ ๊ด๋ จ ์์ ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํ๋ฅผ ํ์ธํด์ผ ํ ๋.
- ํ ์คํธ ๊ฐ์ ์๋ ์ฆ๊ฐ ID๊ฐ ์ ์ง๋์ด์ผ ํ๋ ์ฝ๋(์ผ๋ฐ์ ์ผ๋ก ์ข์ ๊ดํ์ ์๋)๋ฅผ ์ฌ์ฉํ ๋.
TransactionTestCase ์ฌ์ฉ ์ ์ค์ ๊ณ ๋ ค์ฌํญ
TransactionTestCase
๋ ํธ๋์ญ์
์ ์ปค๋ฐํ๊ธฐ ๋๋ฌธ์ ๋ค์ ์ฌํญ์ ์ ๋
ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค:
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๋ฆฌ: ํ์ ํ
์คํธ์ ์ํฅ์ ์ฃผ์ง ์๋๋ก ํ
์คํธ ์ค์ ์์ฑ๋ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก ์ ๋ฆฌํด์ผ ํ ์ ์์ต๋๋ค.
setUp
๋ฐtearDown
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์. - ํ
์คํธ ๊ฒฉ๋ฆฌ:
TransactionTestCase
๋TestCase
์ ๋์ผํ ์์ค์ ํ ์คํธ ๊ฒฉ๋ฆฌ๋ฅผ ์ ๊ณตํ์ง ์์ต๋๋ค. ํ ์คํธ ๊ฐ์ ์ ์ฌ์ ์ธ ์ํธ์์ฉ์ ์ ์ํ๊ณ , ํ ์คํธ๊ฐ ์ด์ ํ ์คํธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ ์์กดํ์ง ์๋๋ก ํ์ธ์. - ์ฑ๋ฅ:
TransactionTestCase
๋ ํธ๋์ญ์ ์ ์ปค๋ฐํ๋ ๊ณผ์ ์ด ํฌํจ๋๋ฏ๋กTestCase
๋ณด๋ค ๋๋ฆด ์ ์์ต๋๋ค. ์ ์คํ๊ฒ, ํ์ํ ๋๋ง ์ฌ์ฉํ์ธ์.
์ฅ๊ณ (Django) ํ ์คํ ์ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
์ฅ๊ณ ์์ ํ ์คํธ๋ฅผ ์์ฑํ ๋ ์ ๋ ํด์ผ ํ ๋ช ๊ฐ์ง ๋ชจ๋ฒ ์ฌ๋ก๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๋ช ํํ๊ณ ๊ฐ๊ฒฐํ ํ ์คํธ ์์ฑ: ํ ์คํธ๋ ์ดํดํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์์ผ ํฉ๋๋ค. ํ ์คํธ ๋ฉ์๋์ ๋จ์ธ๋ฌธ์ ์์ ์ ์ธ ์ด๋ฆ์ ์ฌ์ฉํ์ธ์.
- ํ ๋ฒ์ ํ๋์ฉ ํ ์คํธ: ๊ฐ ํ ์คํธ ๋ฉ์๋๋ ์ฝ๋์ ๋จ์ผ ์ธก๋ฉด์ ํ ์คํธํ๋ ๋ฐ ์ง์คํด์ผ ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํ ์คํธ๊ฐ ์คํจํ์ ๋ ์คํจ์ ์์ธ์ ์ฝ๊ฒ ์๋ณํ ์ ์์ต๋๋ค.
- ์๋ฏธ ์๋ ๋จ์ธ๋ฌธ ์ฌ์ฉ: ์ฝ๋์ ์์ ๋์์ ๋ช ํํ๊ฒ ํํํ๋ ๋จ์ธ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ธ์. ์ฅ๊ณ ๋ ๋ค์ํ ์๋๋ฆฌ์ค์ ๋ง๋ ํ๋ถํ ๋จ์ธ ๋ฉ์๋ ์ธํธ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- Arrange-Act-Assert ํจํด ๋ฐ๋ฅด๊ธฐ: Arrange-Act-Assert(์ค๋น-์คํ-๊ฒ์ฆ) ํจํด์ ๋ฐ๋ผ ํ ์คํธ๋ฅผ ๊ตฌ์ฑํ์ธ์: ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ์ค๋นํ๊ณ (Arrange), ํ ์คํธ ๋์ ์ฝ๋๋ฅผ ์คํํ๊ณ (Act), ์์ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ฆํฉ๋๋ค(Assert).
- ํ ์คํธ ์๋ ์ ์ง: ๋๋ฆฐ ํ ์คํธ๋ ๊ฐ๋ฐ์๋ค์ด ์์ฃผ ์คํํ๋ ๊ฒ์ ๊บผ๋ฆฌ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. ์คํ ์๊ฐ์ ์ต์ํํ๋๋ก ํ ์คํธ๋ฅผ ์ต์ ํํ์ธ์.
- ํ ์คํธ ๋ฐ์ดํฐ์ ํฝ์ค์ฒ(fixture) ์ฌ์ฉ: ํฝ์ค์ฒ๋ ํ ์คํธ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ด๊ธฐ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๋ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ ๋๋ค. ์ผ๊ด์ฑ ์๊ณ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํด ํฝ์ค์ฒ๋ฅผ ์ฌ์ฉํ์ธ์. ID๋ฅผ ํ๋์ฝ๋ฉํ๋ ๊ฒ์ ํผํ๊ธฐ ์ํด ํฝ์ค์ฒ์ ์์ฐ ํค(natural keys)๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์.
- pytest์ ๊ฐ์ ํ ์คํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ ๊ณ ๋ ค: ์ฅ๊ณ ์ ๋ด์ฅ ํ ์คํ ํ๋ ์์ํฌ๋ ๊ฐ๋ ฅํ์ง๋ง, pytest์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ๊ณผ ์ ์ฐ์ฑ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
- ๋์ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง ์ถ๊ตฌ: ์ฝ๋๊ฐ ์ฒ ์ ํ ํ ์คํธ๋์๋์ง ํ์ธํ๊ธฐ ์ํด ๋์ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ๋ชฉํ๋ก ํ์ธ์. ์ปค๋ฒ๋ฆฌ์ง ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ์ธก์ ํ๊ณ ๋ ๋ง์ ํ ์คํธ๊ฐ ํ์ํ ์์ญ์ ์๋ณํ์ธ์.
- CI/CD ํ์ดํ๋ผ์ธ์ ํ ์คํธ ํตํฉ: ์ง์์ ํตํฉ ๋ฐ ์ง์์ ๋ฐฐํฌ(CI/CD) ํ์ดํ๋ผ์ธ์ ์ผ๋ถ๋ก ํ ์คํธ๋ฅผ ์๋์ผ๋ก ์คํํ์ธ์. ์ด๋ฅผ ํตํด ๊ฐ๋ฐ ๊ณผ์ ์ด๊ธฐ์ ๋ชจ๋ ํ๊ท๋ฅผ ๋ฐ๊ฒฌํ ์ ์์ต๋๋ค.
- ์ค์ ์๋๋ฆฌ์ค๋ฅผ ๋ฐ์ํ๋ ํ ์คํธ ์์ฑ: ์ฌ์ฉ์๊ฐ ์ค์ ๋ก ์ํธ์์ฉํ๋ ๋ฐฉ์์ ๋ชจ๋ฐฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ ์คํธํ์ธ์. ์ด๋ ๊ฒ ํ๋ฉด ๊ฐ๋จํ ๋จ์ ํ ์คํธ์์๋ ๋๋ฌ๋์ง ์์ ์ ์๋ ๋ฒ๊ทธ๋ฅผ ๋ฐ๊ฒฌํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ํผ์ ํ ์คํธํ ๋ ๊ตญ์ ์ฃผ์์ ์ ํ๋ฒํธ์ ๋ค์ํ ํ์์ ๊ณ ๋ คํ์ธ์.
๊ตญ์ ํ(i18n)์ ํ ์คํ
์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ๋์์ผ๋ก ์ฅ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ ๋๋ ๊ตญ์ ํ(i18n)์ ํ์งํ(l10n)๋ฅผ ๊ณ ๋ คํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ํ ์คํธ๊ฐ ๋ค๋ฅธ ์ธ์ด, ๋ ์ง ํ์, ํตํ ๊ธฐํธ๋ฅผ ๋ค๋ฃจ๋์ง ํ์ธํ์ธ์. ๋ช ๊ฐ์ง ํ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๋ค๋ฅธ ์ธ์ด ์ค์ ์ผ๋ก ํ
์คํธ: ์ฅ๊ณ ์
override_settings
๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ์ธ์ด ์ค์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ํ ์คํธํ์ธ์. - ํ ์คํธ์ ํ์งํ๋ ๋ฐ์ดํฐ ์ฌ์ฉ: ํ ์คํธ ํฝ์ค์ฒ ๋ฐ ํ ์คํธ ๋ฉ์๋์ ํ์งํ๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ค๋ฅธ ๋ ์ง ํ์, ํตํ ๊ธฐํธ ๋ฐ ๊ธฐํ ๋ก์ผ์ผ๋ณ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋์ง ํ์ธํ์ธ์.
- ๋ฒ์ญ ๋ฌธ์์ด ํ ์คํธ: ๋ฒ์ญ ๋ฌธ์์ด์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋ฒ์ญ๋๊ณ ๋ค๋ฅธ ์ธ์ด์์ ์ฌ๋ฐ๋ฅด๊ฒ ๋ ๋๋ง๋๋์ง ํ์ธํ์ธ์.
localize
ํ ํ๋ฆฟ ํ๊ทธ ์ฌ์ฉ: ํ ํ๋ฆฟ์์localize
ํ ํ๋ฆฟ ํ๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์ ํ์ฌ ๋ก์ผ์ผ์ ๋ฐ๋ผ ๋ ์ง, ์ซ์ ๋ฐ ๊ธฐํ ๋ก์ผ์ผ๋ณ ๋ฐ์ดํฐ๋ฅผ ํ์ํํ์ธ์.
์์ : ๋ค๋ฅธ ์ธ์ด ์ค์ ์ผ๋ก ํ ์คํธํ๊ธฐ
from django.test import TestCase
from django.utils import translation
from django.conf import settings
class InternationalizationTest(TestCase):
def test_localized_date_format(self):
original_language = translation.get_language()
try:
translation.activate('de') # ๋
์ผ์ด ํ์ฑํ
with self.settings(LANGUAGE_CODE='de'): # ์ค์ ์์ ์ธ์ด ์ค์
from django.utils import formats
from datetime import date
d = date(2024, 1, 20)
formatted_date = formats.date_format(d, 'SHORT_DATE_FORMAT')
self.assertEqual(formatted_date, '20.01.2024')
finally:
translation.activate(original_language) # ์๋ ์ธ์ด๋ก ๋ณต์
์ด ์์ ๋ ์ฅ๊ณ ์ translation
๋ฐ formats
๋ชจ๋์ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ์ธ์ด ์ค์ ์ผ๋ก ๋ ์ง ํ์์ ํ
์คํธํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
๊ฒฐ๋ก
TestCase
์ TransactionTestCase
์ ์ฐจ์ด์ ์ ์ดํดํ๋ ๊ฒ์ ์ฅ๊ณ ์์ ํจ๊ณผ์ ์ด๊ณ ์ ๋ขฐํ ์ ์๋ ํ
์คํธ๋ฅผ ์์ฑํ๋ ๋ฐ ํ์์ ์
๋๋ค. TestCase
๋ ๋๋ถ๋ถ์ ํ
์คํธ ์๋๋ฆฌ์ค์์ ์ผ๋ฐ์ ์ผ๋ก ์ ํธ๋๋ ์ ํ์ผ๋ก, ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ณ ๊ตฌ์ฑ ์์๋ฅผ ๊ฒฉ๋ฆฌํ์ฌ ๋น ๋ฅด๊ณ ํจ์จ์ ์ผ๋ก ํ
์คํธํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. TransactionTestCase
๋ ์๊ทธ๋์ด๋ ์์์ ํธ๋์ญ์
๊ณผ ๊ฐ์ด ์ฌ๋ฌ ํธ๋์ญ์
์ ๊ฑธ์น ๋ณต์กํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ์์ฉ์ ํ
์คํธํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค. ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๊ณ ๊ตญ์ ํ ์ธก๋ฉด์ ๊ณ ๋ คํจ์ผ๋ก์จ, ์ฅ๊ณ ์ ํ๋ฆฌ์ผ์ด์
์ ํ์ง๊ณผ ์ ์ง๋ณด์์ฑ์ ๋ณด์ฅํ๋ ๊ฒฌ๊ณ ํ ํ
์คํธ ์ค์ํธ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.