یه کله با یه عالمه سوال ( برنامه نویس وب نیمچه حرفه ای )
Django way s2, Database Mocking ep1
خب یه بخش دیگه از روش های بهتر کار کردن با جنگو رو قصد دارم در اینجا با شما بررسی کنیم قبل از هرچیزی یه توضیح در مورد اسم این نمونه پست ها بدم شماره اول که بعد از s نوشته شده شماره پست هست شماره ای که بعد از ep نوشته شده تعداد پستایی که تا الان در مورد یه مبحث خواص پست گزاشتم
میتونید از اینجا : Django way (روشهای بهتر کار کردن با جنگو) پست قبلی رو بخونید
این مبحث هم به احتمال زیاد در چند بخش ادامه پیدا کنه
اول از همه طرح مسيله :
امروزه برنامه ها رشد خیلی زیادی کردن و در تولید یک برنامه باید سرعت در توسعه و stable بودن کد ها رو کنار هم پیاد کرد برای همین متدولوژی های مختلفی برای پیش بردن یک پروژه ارايه شده که در اکثر اونها تست کردن کد ها و coverage گرفتن از اونها حرف اول رو میزنه مسلما جنگو هم از این قضیه هم نقش خودش رو ایفا کرده و روش هایی برای آسون کردن تست نویسی درست کرده
من توی این پست از rest framework استفاده میکنم
خب بریم ببینیم که چطور یه تست کوچیک میشه برای api خودمون بنویسیم:
به فرض داریم :
# ./product/models.py
from django.db import models
class Product(models.model):
name = models.CharField(max_length=250)
description = models.TextField(max_length=250, blank=True, null=True)
image = models.ImageField(blank=True, null=True)
price = models.FloatField()
# ./product/api/serializer.py
from rest_framework import serializers
from product.models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Prodcut
fields = '__all__'
# ./product/api/views.py
from .serializer import ProductSerializer
from from product.models import Product
from rest_framework import viewsets
class ProductViewSet(viewsets.ModelViewSet):
serializer_class = ProductSerializer
query_set = Product.objects.all()
# ./prodcut/urls.py
from rest_framework.routers import SimpleRouter
from .api import views as api_views
urlpatterns = [
]
product_router = SimpleRouter()
product_router.register('product', api_views.ProductViewSet, basename='product')
api_patterns = product_router.urls
خب حالا برنامه ما حاضره و در حالت عادی میخوایم تستش کنیم مسلما تستمون یه چیزی شبیه این میشه :
#./prodcut/tests.py
from rest_framework.test import APITestCase
class ProductTestView(APITestCase):
@classmethod
def setUpTestData(cls):
cls.product_1 = Product.objects.create(
name="Xbox one",
description="i need xbox one please",
price=800000000,
)
cls.product_2 = Product.objects.create(
name="PS4",
description="i need Ps4 right now",
price=3100000000,
)
cls.product_3 = Product.objects.create(
name="need for speed",
description="need for speed most wanted",
price=5000
)
# and....
def test_get_product_list(self):
response = self.client.get(self.url)
assert response.data['result'][0]['name']=="Xbox one"
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['count'],10)
خوب فکر کنم تا اینجاش فهمیدید چه زخمی خوردیم تازه برنامه ما کوچیک هست که تونستیم به همین مقدار کد تمومش کنیم( تازه عکسم من به دیتام اضافه نکردم چون واقعا دردسره) توی دنیای واقعی با دیتا های واقعی هیچ وقت همه چیز به سادگی دو تا فیلد توی مدلامون نیست...
کدای تستمون فوق العاده کثیف و بهم ریخته دیتا های تکراری و... اصلا یه وضعی که موقع دیدنش چشم آدم خون میاد. حالا فرض کن بچه های فرانت یه سری دیتا فیک بخوان تا کاراشون رو تست کنن دیگه نور علی نور
راه حل:
در این مواقع که ما نیاز به دیتای فیک داریم از تکنیک Database Mocking استفاده میکنیم
به نقل از این منبع : https://wiki.genexus.com/
تکنیک Database Mocking روشی برای شبیه سازی دیتابیس اصلی به همراه تعدادی رکورد برای انجام تست های مورد نیاز است
یکی از راحت ترین روش ها در پایتون برای Database Mocking استفاده از ماژول factory_boy و faker هست که کار را فوق العاده راحت میکنن همچنین ماژول factory_boy مدل های جنگو رو به صورت درونی ساپورت میکنه و توی داکیومنتش هم مثال های خوبی داره که راحت میتونی باهاش کارتون رو راه بندازید ماژول faker هم برای ساختن دیتا هم فیک و الکی از lorem_ipsum تا رمز و پسور فیک و حتی اسم شهر و کشور رو میشه باهاش تولید کرد البته factory_boy به صورت درونی ماژول faker رو هم ساپورت میکنه و نیازی نیست که به صورت مستقیم از faker استفاده بشه.
( یه فکت جالب در مورد ماژول factory_boy اینه که موقع ساخت این ماژول از تکنیک های یه ماژول قدیمی تر به توی زبان روبی به اسم factory_girl استفاده شده :)))) )
ماژول factory_boy چطور کار میکنه :
برای کار با این ماژول بهتره که توی پوشه اپمون یه فایل به اسم factories.py بسازیم و کدمون رو اینجوری بنویسیم:
#./product/factories.py
import factory
from factory import django
from .models import Product
class ProductFactory(django.DjangoModelFactory):
name = factory.Faker('name')
image = django.ImageField(color='blue')
description = factory.Faker("text", max_nb_chars=200)
price = factory.Faker("random_int", min=1000, max=9999999)
class Meta:
model = Product
خب حالا برای ساخت دیتا توی تستمون این کارو میکنیم :
#./prodcut/tests.py
from rest_framework.test import APITestCase
from .factories import ProductFactory
class ProductTestView(APITestCase):
@classmethod
def setUpTestData(cls):
cls.prodcuts = ProductFactory.create_batch(10)
def test_get_product_list(self):
response = self.client.get(self.url)
assert response.data['result'][0]['name'] == self.product[0].name
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['count'],10)
همون طور که دیدید همه چیز راحت و زیبا و بسیار تمیز شد همه چیز سر جای خودشه و موقع عوض شدن api به خاطر به هم ریختن تست هامون گریه نمیکنیم :))
این اولین بخش از قسمتای کار با ماژول factory boy بود چند قسمت دیگه هم در موردشون حرف خواهم زد اگه دوست داشتید میتونید منو فالو کنید تا بقیه قسمت ها رو راحت پیدا کنید
مطلبی دیگر از این انتشارات
کانال های یوتیوب برای بازی سازی (به خصوص یونیتی)!!!!
مطلبی دیگر از این انتشارات
من می خواهم برنامه نویس شوم - قسمت دوم
مطلبی دیگر از این انتشارات
اگه وب سرویس نبودش...