وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

تست واحد در پایتون با Unittest

0 11
زمان لازم برای مطالعه: 8 دقیقه


معرفی

تقریباً در همه زمینه‌ها، محصولات قبل از عرضه به بازار به طور کامل مورد آزمایش قرار می‌گیرند تا از کیفیت آن اطمینان حاصل شود و مطابق با هدف کار کند.

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

روش ها و روش های مختلفی برای تست نرم افزار ما وجود دارد که در این مقاله تمرکز می کنیم روی آزمایش برنامه های پایتون با استفاده از واحد آزمایش چارچوب.

تست واحد در مقابل سایر اشکال تست

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

  • تست غیر عملکردی: به منظور بررسی و بررسی جنبه های غیر کاربردی نرم افزار مانند قابلیت اطمینان، امنیت، در دسترس بودن و مقیاس پذیری است. نمونه هایی از تست های غیر عملکردی عبارتند از تست بار و تست استرس.
  • تست عملکردی: شامل آزمایش نرم افزار ما در برابر الزامات عملکردی برای اطمینان از ارائه عملکرد مورد نیاز است. برای مثال، می‌توانیم با شبیه‌سازی آن سناریو و بررسی ایمیل، آزمایش کنیم که آیا پلتفرم خرید ما پس از ثبت سفارش‌ها، برای کاربران ایمیل ارسال می‌کند یا خیر.

تست واحد در کنار تست عملکردی قرار می گیرد تست ادغام و تست رگرسیون.

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

واحد در اینجا به کوچکترین قسمت یک سیستم اشاره دارد که به یک عملکرد واحد دست می یابد و قابل آزمایش است. هدف از آزمایش واحد تأیید این است که هر جزء از یک سیستم مطابق انتظار عمل می کند که به نوبه خود تأیید می کند که کل سیستم الزامات عملکردی را برآورده کرده و ارائه می دهد.

آزمایش واحد عموماً قبل از آزمایش یکپارچه سازی انجام می شود، زیرا برای تأیید اینکه قسمت های یک سیستم به خوبی با هم کار می کنند، ابتدا باید بررسی کنیم که آنها به صورت جداگانه کار می کنند. همچنین به طور کلی توسط توسعه دهندگانی که اجزای جداگانه را در طول توسعه می سازند، انجام می شود process.

مزایای تست واحد

تست واحد از این جهت مفید است که باگ ها و مشکلات را در مراحل اولیه توسعه برطرف می کند process و در نهایت سرعت آن را افزایش می دهد.

هزینه رفع اشکالات شناسایی شده در طول آزمایش واحد نیز در مقایسه با رفع آنها در طول آزمایش ادغام یا در زمان تولید پایین است.

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

Unittest Framework

با الهام از چارچوب تست JUnit برای جاوا، unittest یک چارچوب آزمایشی برای برنامه‌های پایتون است که از زمان پایتون 2.1 با توزیع پایتون همراه است. گاهی اوقات به آن اشاره می شود PyUnit. این فریم ورک از اتوماسیون و تجمیع تست‌ها و کد راه‌اندازی و خاموش کردن مشترک برای آن‌ها پشتیبانی می‌کند.

از طریق مفاهیم زیر به این امر و موارد دیگر دست می یابد:

  • دستگاه تست: آمادگی لازم برای اجرای آزمون ها و هرگونه اقدامی را که باید پس از پایان آزمون انجام شود را مشخص می کند. تجهیزات می تواند شامل راه اندازی و اتصال پایگاه داده، ایجاد فایل ها یا دایرکتوری های موقت، و پاکسازی یا حذف بعدی فایل ها پس از اتمام آزمایش باشد.
  • مورد تست: به آزمون فردی اطلاق می شود که یک پاسخ خاص را در یک سناریوی معین با ورودی های خاص بررسی می کند.
  • مجموعه تست: نشان دهنده مجموعه ای از موارد آزمایشی است که مرتبط هستند و باید با هم اجرا شوند.
  • دونده تست: اجرای تست ها را هماهنگ می کند و نتایج تست را ارائه می دهد process به کاربر از طریق یک رابط کاربری گرافیکی، terminal یا گزارشی که در پرونده ای نوشته شده است.

unittest تنها فریمورک آزمایشی پایتون موجود نیست، دیگران شامل آن می‌شوند Pytest، چارچوب ربات، کاهو برای BDD، و رفتار چارچوب.

اگر علاقه مند به مطالعه بیشتر در مورد توسعه تست محور در پایتون با PyTest هستید، ما شما را تحت پوشش قرار داده ایم!

Unittest Framework در عمل

ما قصد داریم به بررسی unittest چارچوب با ساختن یک برنامه ماشین حساب ساده و نوشتن تست ها برای تأیید اینکه مطابق انتظار کار می کند. ما استفاده خواهیم کرد توسعه تست محور process با شروع با تست‌ها و سپس اجرای عملکرد برای موفقیت در آزمون‌ها.

اگرچه توسعه برنامه پایتون در یک محیط مجازی تمرین خوبی است، برای این مثال اجباری نخواهد بود زیرا unittest با توزیع پایتون ارسال می شود و ما برای ساخت ماشین حساب خود به هیچ بسته خارجی دیگری نیاز نخواهیم داشت.

ماشین حساب ما عملیات جمع، تفریق، ضرب و تقسیم ساده را بین دو عدد صحیح انجام می دهد. این الزامات تست های عملکردی ما را با استفاده از unittest چارچوب.

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

ماشین حساب ما یک خواهد بود SimpleCalculator کلاس با توابعی برای رسیدگی به چهار عملیات مورد انتظار از آن. اجازه دهید آزمایش را با نوشتن تست های عملیات جمع در ما شروع کنیم test_simple_calculator.py:

import unittest
from simple_calculator import SimpleCalculator

class AdditionTestSuite(unittest.TestCase):
    def setUp(self):
        """ Executed before every test case """
        self.calculator = SimpleCalculator()

    def tearDown(self):
        """ Executed after every test case """
        print("\ntearDown executing after the test case. Result:")

    def test_addition_two_integers(self):
        result = self.calculator.sum(5, 6)
        self.assertEqual(result, 11)

    def test_addition_integer_string(self):
        result = self.calculator.sum(5, "6")
        self.assertEqual(result, "ERROR")

    def test_addition_negative_integers(self):
        result = self.calculator.sum(-5, -6)
        self.assertEqual(result, -11)
        self.assertNotEqual(result, 11)


if __name__ == "__main__":
    unittest.main()

ما با واردات شروع می کنیم unittest ماژول و ایجاد یک مجموعه آزمایشی(AdditionTestSuite) برای عملیات جمع.

در آن، یک را ایجاد می کنیم setUp() روشی که نامیده می شود قبل از هر مورد آزمایشی برای ایجاد ما SimpleCalculator شیئی که برای انجام محاسبات استفاده خواهد شد.

این tearDown() روش اجرا می شود بعد از هر مورد آزمایشی و از آنجایی که در حال حاضر استفاده زیادی از آن نداریم، فقط از آن استفاده خواهیم کرد print نتایج هر آزمون

توابع test_addition_two_integers()، test_addition_integer_string() و test_addition_negative_integers() موارد آزمایش ما هستند انتظار می رود که ماشین حساب دو عدد صحیح مثبت یا منفی را اضافه کند و مجموع را برگرداند. هنگامی که با یک عدد صحیح و یک رشته ارائه می شود، ماشین حساب ما قرار است یک خطا را برگرداند.

این assertEqual() و assertNotEqual() توابعی هستند که برای اعتبارسنجی خروجی ماشین حساب ما استفاده می شوند. این assertEqual() تابع بررسی می کند که آیا دو مقدار ارائه شده برابر هستند یا خیر، در مورد ما، ما انتظار داریم که مجموع شود 5 و 6 بودن 11، بنابراین ما این مقدار را با مقدار برگشتی توسط ماشین حساب مقایسه می کنیم.

اگر دو مقدار با هم برابر باشند، آزمون قبول شده است. سایر توابع ادعایی ارائه شده توسط unittest عبارتند از:

  • assertTrue(a): بررسی می کند که آیا عبارت ارائه شده است یا خیر true
  • assertGreater(a, b): بررسی می کند که آیا a بزرگتر است از b
  • assertNotIn(a, b): بررسی می کند که آیا a هست در b
  • assertLessEqual(a, b): بررسی می کند که آیا a کمتر یا مساوی است b
  • و غیره…

فهرستی از این ادعاها را می توان در این برگه تقلب.

وقتی فایل تست را اجرا می کنیم، خروجی زیر است:

$ python3 test_simple_calulator.py

tearDown executing after the test case. Result:
E
tearDown executing after the test case. Result:
E
tearDown executing after the test case. Result:
E
======================================================================
ERROR: test_addition_integer_string (__main__.AdditionTestSuite)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_simple_calulator.py", line 22, in test_addition_integer_string
    result = self.calculator.sum(5, "6")
AttributeError: 'SimpleCalculator' object has no attribute 'sum'

======================================================================
ERROR: test_addition_negative_integers (__main__.AdditionTestSuite)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_simple_calulator.py", line 26, in test_addition_negative_integers
    result = self.calculator.sum(-5, -6)
AttributeError: 'SimpleCalculator' object has no attribute 'sum'

======================================================================
ERROR: test_addition_two_integers (__main__.AdditionTestSuite)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_simple_calulator.py", line 18, in test_addition_two_integers
    result = self.calculator.sum(5, 6)
AttributeError: 'SimpleCalculator' object has no attribute 'sum'

----------------------------------------------------------------------
Ran 3 tests in 0.001s

FAILED (errors=3)

در بالای خروجی، ما می توانیم اجرای آن را مشاهده کنیم tearDown() از طریق چاپ پیامی که مشخص کردیم عمل کنید. به دنبال آن نامه آمده است E و پیام های خطا ناشی از اجرای آزمایش های ما.

سه نتیجه ممکن برای یک آزمون وجود دارد، می تواند قبول شود، شکست بخورد یا با خطا مواجه شود. این unittest چارچوب سه سناریو را با استفاده از:

  • یک نقطه تمام (.): نشان دهنده قبولی در آزمون است
  • حرف “F”: نشان دهنده شکست در آزمون است
  • حرف “E”: نشان دهنده خطایی در حین اجرای تست است

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

class SimpleCalculator:
    def sum(self, a, b):
        """ Function to add two integers """
        return a + b

ماشین حساب ما اکنون آماده است تا دو عدد را اضافه کند، اما برای اینکه مطمئن شویم مطابق انتظار عمل می کند، اجازه دهید عدد را حذف کنیم. tearDown() از تست های ما استفاده کنید و تست های ما را یک بار دیگر اجرا کنید:

$ python3 test_simple_calulator.py
E..
======================================================================
ERROR: test_addition_integer_string (__main__.AdditionTestSuite)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_simple_calulator.py", line 22, in test_addition_integer_string
    result = self.calculator.sum(5, "6")
  File "/Users/robley/Desktop/code/python/unittest_demo/src/simple_calculator.py", line 7, in sum
    return a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'

----------------------------------------------------------------------
Ran 3 tests in 0.002s

FAILED (errors=1)

خطاهای ما از 3 به یک بار کاهش یافته است. خلاصه گزارش روی خط اول E.. نشان می دهد که یک تست منجر به خطا شد و نتوانست اجرا را کامل کند و دو تست باقی مانده با موفقیت انجام شد. برای انجام اولین قبولی تست، باید تابع جمع خود را به صورت زیر تغییر دهیم:

    def sum(self, a, b):
        if isinstance(a, int) and isinstance(b, int):
            return a + b

وقتی یک بار دیگر تست های خود را اجرا می کنیم:

$ python3 test_simple_calulator.py
F..
======================================================================
FAIL: test_addition_integer_string (__main__.AdditionTestSuite)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_simple_calulator.py", line 23, in test_addition_integer_string
    self.assertEqual(result, "ERROR")
AssertionError: None != 'ERROR'

----------------------------------------------------------------------
Ran 3 tests in 0.001s

FAILED (failures=1)

این بار، تابع جمع ما تا پایان اجرا می شود اما تست ما با شکست مواجه می شود. این به این دلیل است که وقتی یکی از ورودی‌ها یک عدد صحیح نیست، هیچ مقداری برنمی‌گردانیم. ادعای ما مقایسه می کند None به ERROR و از آنجایی که آنها برابر نیستند، آزمون شکست می خورد. برای قبولی در آزمون ما باید خطای موجود را برگردانیم sum() تابع:

def sum(self, a, b):
    if isinstance(a, int) and isinstance(b, int):
        return a + b
    else:
        return "ERROR"

و هنگامی که آزمایش های خود را اجرا می کنیم:

$ python3 test_simple_calulator.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

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

ما همچنین می توانیم آزمایش کنیم که آیا یک استثنا مطرح شده است. به عنوان مثال، وقتی یک عدد بر صفر تقسیم می شود، عدد ZeroDivisionError استثنا مطرح می شود. در ما DivisionTestSuite، می توانیم تأیید کنیم که آیا استثنا مطرح شده است:

class DivisionTestSuite(unittest.TestCase):
    def setUp(self):
        """ Executed before every test case """
        self.calculator = SimpleCalculator()

    def test_divide_by_zero_exception(self):
        with self.assertRaises(ZeroDivisionError):
            self.calculator.divide(10, 0)

این test_divide_by_zero_exception() را اجرا خواهد کرد divide(10, 0) عملکرد ماشین حساب ما را نشان می دهد و تأیید می کند که استثنا واقعاً مطرح شده است. ما می توانیم اجرا کنیم DivisionTestSuite به صورت مجزا به شرح زیر:

$ python3 -m unittest test_simple_calulator.DivisionTestSuite.test_divide_by_zero_exception
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

مجموعه آزمایشی عملکرد تقسیم کامل را می‌توانید در اصل پیوند زیر در کنار مجموعه‌های آزمایشی برای عملکرد ضرب و تفریق پیدا کنید.

نتیجه

در این مقاله به بررسی آن پرداخته ایم unittest چارچوب و موقعیت هایی را که در هنگام توسعه برنامه های پایتون مورد استفاده قرار می گیرد، شناسایی کرد. این unittest چارچوب، همچنین به عنوان شناخته شده است PyUnit، به طور پیش فرض با توزیع پایتون بر خلاف سایر چارچوب های آزمایشی عرضه می شود. به روش TDD، ما تست‌ها را برای یک ماشین حساب ساده نوشتیم، تست‌ها را اجرا کردیم و سپس عملکرد را پیاده‌سازی کردیم تا تست‌ها موفق شوند.

این unittest چارچوب عملکردی را برای ایجاد و گروه بندی موارد آزمایشی و بررسی خروجی ماشین حساب ما در برابر خروجی مورد انتظار برای تأیید اینکه مطابق انتظار کار می کند ارائه می دهد.

ماشین حساب کامل و مجموعه های آزمایشی را می توانید در اینجا پیدا کنید اصل مطلب روی GitHub.

(برچسب‌ها به ترجمه)# python



منتشر شده در 1403-01-19 10:28:03

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید