هنگام نوشتن نرم افزار، می توانید از طریق تست، صحت کارکرد آن را تایید کنید. تست را می توان به طور کلی به عنوان فرآیند اجرای نرم افزار به روش های خاص تعریف کرد تا اطمینان حاصل شود که همانطور که در نظر گرفته شده است رفتار می کند.
آزمایش موفقیت آمیز می تواند به شما اطمینان دهد که با افزودن کد، ویژگی های جدید یا حتی ارتقاء وابستگی های خود، نرم افزاری که قبلاً نوشته اید به همان روشی که انتظار دارید به کار خود ادامه می دهد. آزمایش همچنین می تواند به محافظت از نرم افزار شما در برابر سناریوهای بعید یا ورودی های غیرمنتظره کمک کند.
برخی از نمونههای رفتار در وب که ممکن است بخواهید آزمایش کنید عبارتند از:
- حصول اطمینان از اینکه ویژگی یک وب سایت به درستی کار می کند وقتی دکمه ای کلیک می شود.
- تأیید اینکه یک تابع پیچیده نتایج صحیح را ایجاد می کند.
- انجام عملی که نیاز به ورود کاربر دارد.
- بررسی اینکه یک فرم به درستی خطا را هنگام وارد کردن دادههای نادرست گزارش میکند.
- اطمینان از اینکه یک برنامه وب پیچیده زمانی که کاربر دارای پهنای باند بسیار کم است یا آفلاین است به کار خود ادامه می دهد.
تست خودکار در مقابل تست دستی
شما می توانید نرم افزار خود را به دو روش کلی تست کنید: تست خودکار و تست دستی.
آزمایش دستی شامل انسانها میشود که نرمافزار را مستقیماً اجرا میکنند، مانند بارگذاری یک وبسایت در مرورگر خود، و تأیید اینکه آنگونه که انتظار میرود عمل میکند. تست های دستی برای ایجاد یا تعریف ساده هستند - برای مثال، آیا سایت شما می تواند بارگذاری شود؟ آیا میتوانید این اعمال را انجام دهید؟ - اما هر گذر از آن زمان زیادی برای انسان هزینه دارد. در حالی که انسانها بسیار خلاق هستند، که میتوانند نوعی آزمایش به نام تستهای اکتشافی را فعال کنند، ما هنوز هم میتوانیم در تشخیص شکستها یا ناسازگاریها ضعیف باشیم، بهخصوص زمانی که یک کار را بارها انجام میدهیم.
تست خودکار هر فرآیندی است که به آزمایشها اجازه میدهد تا به طور مکرر توسط رایانه کدگذاری و اجرا شوند تا رفتار مورد نظر نرمافزار شما را تأیید کند، بدون اینکه انسان مراحل مکرری را انجام دهد، مانند راهاندازی یا بررسی نتایج. نکته مهم، هنگامی که تست خودکار پیکربندی شد، می توان آن را به طور مکرر اجرا کرد. این هنوز یک تعریف بسیار گسترده است، و شایان ذکر است که تست های خودکار انواع و اقسام اشکال و اشکال را دارند. اکثر این دوره به آزمایش خودکار به عنوان یک تمرین مربوط می شود.
آزمایش دستی جایگاه خود را دارد، اغلب به عنوان پیشرو برای نوشتن تستهای خودکار، اما همچنین زمانی که تست خودکار بیش از حد غیرقابل اعتماد، دامنه وسیع یا غیرقابل تحمل میشود.
مبانی از طریق یک مثال
برای ما، بهعنوان توسعهدهندگان وب که جاوا اسکریپت یا زبانهای مرتبط را مینویسیم، یک تست خودکار مختصر میتواند اسکریپتی باشد که هر روز، شاید از طریق Node، یا با بارگذاری آن در مرورگر، آن را اجرا میکنید:
import { fibonacci } from "../src/math.js";
if (fibonacci(0) !== 0) {
throw new Error("Invalid 0th fibonacci result");
}
const fib13 = fibonacci(13);
if (fib13 !== 233) {
throw new Error("Invalid 13th fibonacci result, was=${fib13} wanted=233");
}
این یک مثال ساده است که بینش های زیر را ارائه می دهد:
این یک آزمایش است زیرا برخی از نرم افزارها ( تابع فیبوناچی ) را اجرا می کند و با بررسی نتایج آن در برابر مقادیر مورد انتظار، اطمینان حاصل می کند که رفتار آن به روشی که در نظر گرفته شده است عمل می کند. اگر این رفتار درست نباشد، یک خطا ایجاد می کند که جاوا اسکریپت با پرتاب
Error
بیان می کند.حتی اگر ممکن است این اسکریپت را به صورت دستی در ترمینال یا مرورگر خود اجرا کنید، این هنوز یک آزمایش خودکار است زیرا میتواند به طور مکرر بدون نیاز به انجام هر مرحله جداگانه اجرا شود. صفحه بعد، جایی که تست ها اجرا می شوند ، بیشتر توضیح می دهد.
اگرچه این تست از هیچ کتابخانه ای استفاده نمی کند - این جاوا اسکریپت است که می تواند در هر جایی اجرا شود - هنوز یک آزمایش است. ابزارهای زیادی وجود دارند که میتوانند به شما در نوشتن تستها کمک کنند، از جمله مواردی که بعداً در این دوره به آنها پرداخته میشود، اما همه آنها همچنان بر روی اصل اساسی ایجاد خطا در صورت بروز مشکل کار میکنند.
آزمایش کتابخانه ها در عمل
اکثر کتابخانهها یا چارچوبهای تست داخلی دو اصل اولیه را ارائه میکنند که نوشتن تستها را آسانتر میکند: ادعاها و راهی برای تعریف تستهای مستقل. اینها به عنوان بخشی از بخش بعدی، ادعاها و دیگر اصول اولیه به تفصیل پوشش داده خواهند شد. با این حال، در سطح بالا، مهم است که به یاد داشته باشید که تقریباً تمام تستهایی که میبینید یا مینویسید در نهایت از این نوع آزمایشهای اولیه استفاده میکنند.
اظهارات راهی برای ترکیب بررسی یک نتیجه و ایجاد خطا در صورت بروز مشکل است. به عنوان مثال، میتوانید تست قبلی را با معرفی assert
مختصرتر کنید:
import { fibonacci } from "../src/math.js";
import { assert } from "a-made-up-testing-library";
assert.equal(fibonacci(0), 0, "Invalid 0th fibonacci result");
assert.equal(fibonacci(13), 233, "Invalid 13th fibonacci result");
شما می توانید این آزمون را با تعریف تست های مستقل که به صورت اختیاری در مجموعه ها گروه بندی می شوند، بهبود بخشید. مجموعه زیر به طور مستقل تابع فیبوناچی و تابع کاتالان را آزمایش می کند:
import { fibonacci, catalan } from "../src/math.js";
import { assert, test, suite } from "a-made-up-testing-library";
suite("math tests", () => {
test("fibonacci function", () => {
assert.equal(fibonacci(0), 0, "Invalid 0th fibonacci result");
assert.equal(fibonacci(13), 233, "Invalid 13th fibonacci result");
});
test("relationship between sequences", () => {
const numberToCheck = 4;
const fib = fibonacci(numberToCheck);
const cat = catalan(numberToCheck);
assert.isAbove(fib, cat);
});
});
در این زمینه از تست نرم افزار، تست به عنوان یک اسم به یک مورد آزمایشی اشاره دارد: یک سناریوی منفرد، مستقل، آدرس پذیر، مانند مورد آزمایشی "رابطه بین دنباله ها" در مثال قبلی.
تست هایی که به صورت جداگانه نام گذاری شده اند برای کارهای زیر مفید هستند، از جمله:
- تعیین چگونگی موفقیت یا شکست یک آزمون در طول زمان.
- یک اشکال یا سناریو را با نام برجسته کنید تا بتوانید راحتتر تست کنید که سناریو حل شده است.
- اجرای برخی از تست ها به طور مستقل از سایرین، مانند فیلتر گلوب.
یکی از راههای فکر کردن به موارد آزمایشی استفاده از «سه A» تست واحد است: ترتیب، عمل، و ادعا. هر مورد آزمایشی، در هسته خود، این موارد را انجام خواهد داد:
- برخی از مقادیر یا حالت ها را مرتب کنید (این فقط می تواند داده های ورودی سخت کد شده باشد).
- عملی مانند فراخوانی یک متد را انجام دهید.
- مقادیر خروجی یا وضعیت به روز شده (با استفاده از
assert
) را ثابت کنید.
مقیاس آزمون ها
نمونههای کد در بخش قبل یک تست واحد را توصیف میکنند، زیرا بخشهای جزئی نرمافزار شما را آزمایش میکنند، که اغلب بر روی یک فایل متمرکز میشوند، و در این مورد، فقط خروجی یک تابع واحد است. پیچیدگی تست با در نظر گرفتن کد از چندین فایل، مؤلفه یا حتی سیستم های مختلف به هم پیوسته (گاهی خارج از کنترل شما، مانند یک سرویس شبکه یا رفتار یک وابستگی خارجی) افزایش می یابد. به همین دلیل، انواع تست اغلب بر اساس دامنه یا مقیاس آنها نامگذاری می شوند.
همراه با تست های واحد ، برخی از نمونه های دیگر انواع تست شامل تست جزء ، تست بصری و تست یکپارچه سازی می باشد. هیچ یک از این نام ها تعاریف دقیقی ندارند و ممکن است بسته به پایگاه کد شما معانی متفاوتی داشته باشند، بنابراین به یاد داشته باشید که از آنها به عنوان یک راهنما استفاده کنید و تعاریفی را ارائه دهید که برای شما مناسب باشد. به عنوان مثال، یک جزء تحت آزمایش در سیستم شما چیست؟ برای توسعه دهندگان React، این ممکن است به معنای واقعی کلمه به یک "کامپوننت React" نگاشت شود، اما ممکن است برای توسعه دهندگان در زمینه های دیگر معنای متفاوتی داشته باشد.
مقیاس یک آزمون فردی میتواند آن را درون مفهومی قرار دهد که اغلب به آن «هرم آزمایش» میگویند، که میتواند یک قانون سرانگشتی خوب برای اینکه یک آزمون چه چیزی را بررسی میکند و چگونه اجرا میشود.
این ایده تکرار شده است و اکنون اشکال مختلف دیگری مانند الماس آزمایشی یا مخروط یخ آزمایشی رایج شده است . اولویت های تست نویسی شما احتمالا منحصر به پایگاه کد شما خواهد بود. با این حال، یک ویژگی مشترک این است که تستهای سادهتر، مانند تستهای واحد ، سریعتر اجرا میشوند، نوشتن آسانتر است (بنابراین تعداد بیشتری از آنها را خواهید داشت) و دامنه محدودی را آزمایش میکنند، در حالی که تستهای پیچیدهتر مانند تستهای پایان به انتها نوشتن تست ها دشوار است اما می تواند دامنه وسیع تری را آزمایش کند. در واقع، لایه بالایی بسیاری از «اشکال» آزمایشی به آزمایش دستی تمایل دارد، زیرا برخی از تعاملات کاربر برای کدگذاری در یک تست خودکار بسیار پیچیده است.
این انواع در انواع تست های خودکار گسترش خواهند یافت.
درک خود را بررسی کنید
اکثر کتابخانه ها و چارچوب های آزمایشی چه چیزهای اولیه ای را ارائه می دهند؟
assert()
و تغییرات آن معمولاً شامل میشوند زیرا نوشتن چکها را آسانتر میکنند.test()
تقریباً در همه آزمایشکنندگان گنجانده شده است. این مهم است زیرا کد تست در سطح بالای یک فایل اجرا نمیشود، که به اجراکننده آزمایش اجازه میدهد هر مورد آزمایشی را به عنوان یک واحد مستقل در نظر بگیرد.