021-71053903 [email protected] پشتیبانی از شنبه تا چهارشنبه ساعت 9 الی 16

تست نویسی در جنگو

تست های نوشتن برای برنامه های جنگو

آیا برنامه شما مطابق انتظار اجرا می شود یا در جستجوی راه حل های مرتبط برای آزمایش خروجی برنامه خود هستید؟ این ممکن است کمک کند!

خلاصه: با کمک چارچوب اجرای تست و ابزارهای متفرقه جنگو، می‌توانید درخواست‌ها را شبیه‌سازی کنید، داده‌های تست را وارد کنید، خروجی برنامه خود را تجزیه و تحلیل کنید و در نهایت کد خود را دوباره بررسی کنید.

ما در این مقاله این طور در نظر می گیریم که شما هیچ تجربه ای در زمینه کار کردن با تست نویسی ندارید.

 

اصلا چرا تست نیاز است؟

وقتی کد جدیدی می نویسید، به احتمال زیاد با خطاهایی روبرو می شوید – چه انتظار می رود یا نه. آزمایش سیستمی که کدگذاری کرده اید آن را قابل اعتماد و موثر می کند که در نتیجه کیفیت کد شما را بهبود می بخشد. هرچه موارد تست بیشتر برای یک سیستم طراحی و اجرا شود، کیفیت بالاتری دارد. با این حال، آزمایش یک برنامه وب گاهی اوقات می تواند سخت باشد زیرا از چندین لایه ساخته شده است، از رسیدگی به درخواست در سطح HTTP گرفته تا اعتبارسنجی و پردازش فرم ها و قالب های رندر.

با استفاده از چارچوب اجرای آزمایش جنگو و خدمات متنوع، می‌توانید درخواست‌ها را شبیه‌سازی کنید، داده‌های تست را برای ورودی موارد آزمایشی وارد کنید، خروجی برنامه خود را تجزیه و تحلیل و درک کنید و سپس می‌توانید کد خود را بر این اساس تغییر دهید. اما چگونه می توانیم یک برنامه کاربردی را آزمایش کنیم؟ راه‌های زیادی برای تست نرم‌افزار مانند تست واحد، تست یکپارچه‌سازی، تست رگرسیون، تست دود، تست آلفا، تست بتا و غیره وجود دارد.

 

ابزارهای تست برای یک برنامه جنگو

جنگو یک کتابخانه تست سلسله مراتبی یا رتبه ای را به نام unittest کتابخانه ارائه می دهد. صرف نظر از نام آن، می توان از آن برای تست یکپارچه سازی نیز استفاده کرد. این فریم ورک API و ابزارهایی را برای آزمایش رفتار خاص وب و جنگو یک برنامه اضافه می کند. جنگو همچنین یک API به نام LiveServerTestCaseو ابزارهایی برای استفاده از چارچوب های مختلف برای آزمایش ارائه می دهد.

 

نحوه نوشتن تست در جنگو

برای نوشتن یک تست، می‌توانیم هر کلاس پایه آزمایشی را از django.testماژول وارد کنیم. کلاس‌های پایه آزمایشی مختلفی مانند SimpleTestCase، TransactionTestCase، TestCase، LiveServerTestCase و غیره وجود دارد. سپس، می‌توانید با استفاده از assert(firstArg, secondArg)روش‌های ادعایی که در زیر توضیح داده شده است، روش‌های خاصی بنویسید تا بررسی کنید که آیا عملکردهای برنامه شما مطابق انتظار اجرا می‌شوند یا خیر. بیایید مثال بسیار ساده و سرراست زیر را مرور کنیم.

 

from django.test import TestCase


def concate_two_strings(str1, str2):
    return str1 + str2


class TestExample(TestCase):

    def test_concate_two_strings(self):
    	self.assertEqual(concate_two_strings("Hello, ", "How are you?"), "Hello, How are you?")

 

در کد بالا،

  • ما TestCaseکلاس پایه را برای آزمایش وارد کردیم. شما می توانید از هر کلاس پایه مطابق با ابزار خود استفاده کنید.
  • ما روشی را تعریف کردیم که نام concate_two_stringsآن روش هدف ما برای آزمایش است.
  • ما یک کلاس مشتق شده برای TestCase ایجاد کردیم و یک روش تست به نام تعریف کردیم test_concate_two_strings. روش‌های تست از روش‌های ادعایی خاصی استفاده می‌کنند که به ترتیب True یا False را برمی‌گرداند که نشان می‌دهد آزمون به ترتیب موفق شده یا ناموفق است.

کد بالا آزمون بررسی الحاق دو رشته را با موفقیت پشت سر می گذارد زیرا نتیجه روش هدف مطابق انتظار است.

 

انواع تست در جنگو

عمدتاً دو نوع آزمایش در جنگو وجود دارد:

  • تست واحد – تست انفرادی که بر روی روش های آزمایش به صورت ایزوله تمرکز می کند.
  • تست یکپارچه سازی – تست رفتاری کاربر که بر آزمایش کل یک برنامه به عنوان یک کل تمرکز دارد.

در این مقاله، ما قصد داریم بیشتر در مورد تست واحد تمرکز و بررسی کنیم.

 

Assertion

Assertion روش‌های ضروری هستند که با برگرداندن True یا False تعیین می‌کنند که آیا یک آزمون موفق شده یا ناموفق بوده است. شما می توانید از چندین ادعا در یک آزمون استفاده کنید.

بیایید این مثال را ببینیم:

from django.tests import TestCase

def get_max(num1, num2):
      return num1 if num1>=num2 else num2

class TestExample(TestCase):

      def test_get_max(self):
            self.assertEqual(get_max(4,7),7)

ما یک روش بسیار ساده را انتخاب کرده ایم get_maxکه حداکثر عدد را از دو عدد num1 و num2 برمی گرداند. test_get_maxمتد بالا در کلاس TestExampleبررسی می کند که آیا خروجی روش داده شده با خروجی مورد انتظار مطابقت دارد یا خیر. در اینجا، assertEqualمتد True را برمی گرداند زیرا get_maxمتد عدد مورد انتظار یعنی 7 را برمی گرداند (پارامتر دوم متد assertEqual).

 

مراجع کد

ساختار پوشه

در این مقاله برای تصویرسازی به اپلیکیشن ‘تجارت الکترونیک’ و ماژول ها و فایل های آن اشاره می کنیم. این ساختار ایده آلی است که باید برای برنامه جنگو خود دنبال کنید.

└── ecommerce/
    ├── ecommerce/
    │   ├── wsgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   ├── model.py
    │   └── tests/
    │       ├── test_urls.py
    │       └── test_model.py
    ├── store/
    │   ├── admin.py
    │   ├── views.py
    │   ├── urls.py
    │   ├── model.py
    │   └── tests/
    │       ├── test_views.py
    │       ├── test_model.py
    │       └── test_urls.py
    ├── customer/
    │   ├── admin.py
    │   ├── views.py
    │   ├── urls.py
    │   ├── model.py
    │   └── tests/
    │       ├── test_views.py
    │       ├── test_model.py
    │       └── test_urls.py
    └── manage.py

این یک تمرین خوب است که پوشه ای به نام “Tests” در پوشه های برنامه خود ایجاد کنید و سپس فایل های آزمایشی خود را با فرمت test_{name}.py نام گذاری کنید.

 

 

آدرس های اینترنتی پروژه یا همان URL ها

from django.contrib import admin
from django.urls import path,include
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('store.urls'))
]

urlpatterns+=static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

 

URL های اپلیکیشن

from django.urls import path
from . import views

urlpatterns=[
    path('',views.store,name='store'),
    path('cart/',views.cart,name='cart'),
    path('checkout/',views.checkout,name='checkout'),

    path('update_item/',views.update_item,name='update_item'),
    path('process_order/',views.processOrder,name='process_order'),

]

 

 

Unit Test

تست واحد در جنگو بر روی هر روش به صورت جداگانه متمرکز است. از یک ماژول کتابخانه استاندارد پایتون به نام استفاده unittestمی کند که تست ها را با استفاده از رویکرد مبتنی بر کلاس تعیین می کند. چندین زیر آزمون واحد تست وجود دارد مانند تست URL، تست نماها، تست مدل، تست فرم ها، تست API و غیره. در جنگو، ما می توانیم از این تست ها به طور مستقل استفاده کنیم.

 

تست URL

دو روش وجود دارد که می توانیم URL ها را در برنامه خود آزمایش کنیم

  • استفاده از نمونه مشتری

کلاینت آزمایشی کلاسی از پایتون است که به عنوان یک کاربر ساختگی یا مرورگر وب عمل می کند و به شما امکان می دهد URL ها و نماهای خود را آزمایش کنید و با عملکردهای برنامه جنگو خود تعامل داشته باشید.

from django.test import TestCase

class UrlTest(TestCase):

    def testHomePage(self):
        response = self.client.get('/')
        print(response)

        self.assertEqual(response.status_code, 200)

 

در کد بالا، ما روش تست را تعریف کردیم testHomePage، که در آن شیء پاسخ HTTP را با زدن نشانی اینترنتی GET ‘/’ دریافت کردیم. اگر صفحه بازیابی شود، شی پاسخ حاوی بدنه صفحه و ابرداده های آن مانند عنوان، کد وضعیت و غیره خواهد بود. با اجرای assertEqualروش، به سادگی بررسی می کنیم که آیا کد وضعیت پاسخ 200 است یا خیر. به این معنی که آیا صفحه/URLی که با شی مشتری برخورد کرده بودیم پیدا شد یا نه. اگر پیدا نشد، کد وضعیت 404 خواهد بود و روش تست False را برمی گرداند.

  • استفاده از روش های Reverse و Resolve
from django.test import TestCase
from django.urls import reverse, resolve
from store.views import cart

class UrlTest(TestCase):

    def testCartPage(self):

    	url = reverse('cart')
    	print("Resolve : ", resolve(url))

    	self.assertEquals(resolve(url).func, cart)

در کد بالا، assertEqualsمتد بررسی می‌کند که آیا روش حل‌کننده با نمای سبد خرید مطابقت دارد یا خیر. این آزمون قبول می شود زیرا نتیجه مطابق انتظار است.

حالا بیایید کد اشتباه را امتحان کنیم.

from django.test import TestCase
from django.urls import reverse, resolve

class UrlTest(TestCase):

    def testCartPage(self):

        url = reverse('cart')
        print("Resolve : ", resolve(url))

        self.assertEquals(resolve(url).func, ‘cart’)

متد در assertEqualsکلاس Testing بالا شکست خواهد خورد زیرا مطابقت حل‌کننده نمای سبد خرید را برمی‌گرداند و نه رشته “cart” را که آرگومان دوم روش ادعای داده شده است.

 

تست مدل

بیایید کد زیر را درک کنیم

class Product(models.Model):
    name = models.CharField(max_length=200,null=True)
    price = models.FloatField()
    digital = models.BooleanField(default=False,null=True,blank=True)
    image = models.ImageField(null=True,blank=True)

    def __str__(self):
        return self.name

    @property
    def imageURL(self):
        try:
            url = self.image.url
        except:
            url=''

        return url

 

در کد بالا مدلی به نام Productبا ویژگی هایی مانند نام، قیمت، دیجیتال، تصویر و imageURL تعریف کرده ایم.

from django.test import TestCase
from store.models import Product

class ModelTest(TestCase):

    def testProductModel(self):
        product = Product.objects.create(name="ToyCar", price=800)
        self.assertEquals(str(product), 'ToyCar')
        print("IsInstance : ",isinstance(product,Product))
        self.assertTrue(isinstance(product,Product))

 

اکنون کلاس Testing را ModelTestبا متدی به نام تعریف کرده ایم testProductModel. در آن، یک نمونه محصول با نام «ToyCar» ایجاد می‌شود که بعداً با assertEqualsروشی بررسی کردیم که True را برمی‌گرداند. سپس، بررسی کردیم که آیا نمونه محصول نمونه ای از کلاس Product است یا خیر، بنابراین True برمی گردد و تست انجام می شود.

 

اکنون، بیایید همان کد را امتحان کنیم اما با نام محصول متفاوت (خطا).

from django.test import TestCase
from store.models import Product

class ModelTest(TestCase):

    def testProductModel(self):
        product = Product.objects.create(name="ToyCar", price=800)
        self.assertEquals(str(product), 'ToyCar11')
        print("IsInstance : ",isinstance(product,Product))
        self.assertTrue(isinstance(product,Product))

در کد بالا، متد assertEquals False را برمی‌گرداند زیرا نام محصول «ToyCar» با «ToyCar11» مطابقت ندارد و بنابراین، آزمایش ناموفق خواهد بود.

 

 

 

اجرای تست ها

پس از اتمام نوشتن تست‌ها برای برنامه‌تان، می‌توانید با اجرای دستورات آزمایشی زیر که در ابزار Manage.py نوشته شده‌اند، آن‌ها را اجرا کنید:

python manage.py test

 

برای اجرای آزمایش‌ها به‌طور خاص در یک ماژول برنامه (مثلا ای اینجا ما فقط برای «فروشگاه» اجرا کردیم):

python manage.py test store

 

فقط یک مورد آزمایشی را اجرا کنید:

python manage.py test store.tests.test_urls.py

 

انواع Assertion در جنگو موجود است

assertNotEqual

assertNotEqual(firstArg, secondArg, msg=None)

بررسی می کند که firstArg و secondArg برابر نیستند و بنابراین True در غیر این صورت False (یعنی تست شکست خورده است) را برمی گرداند.

 

assertTrue (یا assertFalse)

assertTrue(expr, msg=None)

 

درست یا نادرست بودن bool(expr) را بررسی می کند.

توجه داشته باشید که این روش bool(expr) را به جای expr به صورت True یا False ارزیابی می کند.

 

assertIsInstance (یا assertNotIsInstance)

assertIsInstance(obj, cls, msg=None)

تعیین می کند که آیا شیء obj یک نمونه (یا نه) از کلاس cls است.

 

 

assertIs (or assertIsNot)

assertIs(firstObj, secondObj, msg=None)

آزمایش می کند که آیا firstObj و secondObj یک شی هستند (یا نه).

 

 

assertIn (or assertNotIn)

assertIn(member, container, msg=None)

بررسی می کند که آیا عضو در ظرف است (یا نه). در نسخه 3.1 موجود است

 

 

assertIsNone (or assertIsNotNone)

assertIsNone(expr, msg=None)

بررسی می کند که آیا expr None است یا خیر.

 

نتیجه گیری

با جمع بندی همه اینها، نوشتن و اجرای تست ها در برنامه جنگو قبل از استقرار آن، تمرین خوبی است. رویکرد آزمایشی در جنگو ساده است و اگر تمام مراحل و قوانین را به طور کامل اجرا کنید، آزمایش می تواند کد بسیار با کیفیت و بدون خطا را در اختیار شما قرار دهد. علاوه بر این، اگر می‌خواهید عمیق‌تر در هسته ماژول‌ها و کتابخانه‌های جنگو جستوجو کنید، درک اسناد رسمی آن بسیار آسان است.

 

 

محمدرضا حسنی

224 مطلب منتشر شده

دانش آموخته رشته فناوری اطلاعات / موسس پایتونی ها

درباره این مطلب نظر دهید !

محصولات فروش پایتونی ها

%60
تخفیف

آموزش فیگما (Figma)

30,000 تومان
2