برنامه نویسی

توسعه تست محور (TDD) با تست Bun

توسعه تست محور (TDD) یک روش قدرتمند برای نوشتن کد تمیز و بدون اشکال است. در این مقاله، نحوه پیاده‌سازی TDD را با استفاده از تست اجراکننده داخلی Bun، Bun Test، که به دلیل سرعت و سادگی خود شناخته شده است، بررسی خواهیم کرد.

TDD چیست؟

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

TDD یک فرآیند توسعه است که مراحل زیر را دنبال می کند:

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

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

راه اندازی پروژه جاوا اسکریپت خود با Bun

اگر Bun را نصب نکرده‌اید، آن را با دنبال کردن دستورالعمل‌های موجود در مستندات Bun JavaScript نصب کنید.
سپس، یک پروژه جدید را راه اندازی کنید:

bun init
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

➜  example bun init
bun init helps you get started with a minimal project and tries to guess sensible defaults. Press ^C anytime to quit

package name (example):
entry point (index.ts):

Done! A package.json file was saved in the current directory.
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

یک فایل آزمایشی در tests دایرکتوری (به عنوان مثال، tests/example.test.js). Bun به طور خودکار فایل هایی را که به آن ختم می شوند شناسایی می کند .test.ts یا .test.js برای آزمایش

mkdir tests
touch tests/example.test.js
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نوشتن اولین آزمون

بیایید با یک مثال ساده شروع کنیم.
ما یک فایل ماشین حساب برای پیاده سازی برخی از توابع ریاضی ایجاد می کنیم.
ابتدا روی یک تابع ساده تمرکز می کنیم، مانند sum()، حتی اگر جاوا اسکریپت قبلاً یک اپراتور افزودن بومی دارد. این به ما اجازه می دهد تا به جای پیچیدگی منطق، بر ساختار آزمون ها تمرکز کنیم.
در اینجا این طرح است:

  • ایجاد یک calculator.ts فایلی که در آن a را تعریف می کنیم sum() تابعی که در ابتدا باز می گردد 0.
  • برای آن تست بنویسید sum() عملکردی که چندین مورد آزمایشی را پوشش می دهد.
  • تست ها را اجرا کنید و تایید کنید که آنها شکست خورده اند.
  • منطق را به روز کنید sum() عملکرد موفقیت آمیز در آزمون ها
  • برای اطمینان از صحت اجرای ما، آزمایش ها را دوباره اجرا کنید.

خود را ایجاد کنید calculator.test.js فایل

در tests/calculator.test.js فایل، می توانید تست های خود را پیاده سازی کنید:

import { describe, expect, it } from "bun:test";
import { sum } from "../calculator";

describe("sum function", () => {
  it("should return the sum of two numbers (both are positive)", () => {
    expect(sum(2, 3)).toBe(5);
  });
  it("should return the sum of two numbers (one is negative)", () => {
    expect(sum(-1, 2)).toBe(1);
  });
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این تست‌ها رفتار آن را تایید می‌کنند sum() تابع، تعریف شده در calculator ماژول تست‌ها با استفاده از کتابخانه تست Bun نوشته شده و در a سازماندهی شده‌اند describe بلوکی با نام “تابع جمع”. این describe() بلوک به گروه بندی تست های “مشابه” کمک می کند. هر کدام it() بلوک سناریوی خاصی را برای آزمایش مشخص می کند. در اینجا چیزی است که هر آزمون انجام می دهد:

  1. تست: جمع دو عدد مثبت
    • توضیحات: “باید مجموع دو عدد را برگرداند (هر دو مثبت هستند)”
    • این تست بررسی می کند که آیا تابع جمع به درستی مجموع دو عدد صحیح مثبت را محاسبه می کند.
    • مثال: sum(2, 3) است انتظار می رود برای بازگشت 5.
  2. تست: جمع کردن یک عدد منفی و یک عدد مثبت
    • توضیحات: “باید مجموع دو عدد را برگرداند (یکی منفی است)”
    • این تست تأیید می کند که تابع جمع به درستی سناریویی را که در آن یک عدد منفی است، کنترل می کند.
    • مثال: sum(-1, 2) است انتظار می رود برای بازگشت 1.

این تست‌ها تضمین می‌کنند که تابع مجموع همانطور که برای سناریوهای جمع پایه انتظار می‌رود رفتار می‌کند، و هم اعداد مثبت و هم ورودی‌های مختلط (مثبت و منفی) را پوشش می‌دهد.

خود را ایجاد کنید calculator.ts فایل

اکنون، می توانید ماژول ماشین حساب خود را ایجاد کنید که آن را صادر می کند sum() تابع
در calculator.ts فایل:

export function sum(a: number, b: number) {
  // Function yet to be implemented
  return 0;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نسخه اول تابع یک مقدار سخت کد شده را برمی گرداند، بنابراین من انتظار دارم که تست ها با شکست مواجه شوند.
اجرای تست ها:

bun test
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اجرای دستور endraw 'bun test' خام با تست های ناموفق

حالا می توانیم منطق را تنظیم کنیم sum() عملکرد در calculator.ts منطق را تنظیم کنید sum() تابع:

export function sum(a: number, b: number) {
  return a + b;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حالا اگر تست ها را اجرا کنید، وضعیت «سبز» خواهید داشت.

اجرای دستور endraw 'bun test' خام با تست های گذرانده شده

آزمایش‌های بازسازی با مجموعه داده

اگر می‌خواهید همان آزمایش‌ها را با سناریوهای مختلف (مقادیر ورودی) اجرا کنید، می‌توانید از آن استفاده کنید each() روش

import { describe, expect, it } from "bun:test";
import { sum } from "../calculator";

const dataset = [
  [2, 3, 5],
  [-1, 2, 1],
];

describe("sum function", () => {
  it.each(dataset)("Sum of %d and %d should be %d", (a, b, expected) => {
    expect(sum(a, b)).toBe(expected);
  });
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

با استفاده از یک رویکرد مبتنی بر مجموعه داده، این کد تابع جمع را از روی آزمایش می کند calculator ماژول این it.each() این روش برای ساده‌سازی موارد آزمایشی تکراری با تکرار روی مجموعه داده‌های ورودی و خروجی‌های مورد انتظار استفاده می‌شود. در اینجا خلاصه ای از نحوه عملکرد آن آمده است:

ابتدا می توانید یک مجموعه داده را تعریف کنید

const dataset = [
  [2, 3, 5],    // Test case 1: Adding 2 and 3 should return 5
  [-1, 2, 1],   // Test case 2: Adding -1 and 2 should return 1
];
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این dataset آرایه ای از آرایه ها است. هر آرایه داخلی نشان دهنده یک مورد آزمایشی است که در آن عناصر با موارد زیر مطابقت دارند:

  • a (اولین عدد برای اضافه کردن)،
  • b (عدد دوم برای اضافه کردن)،
  • مورد انتظار (نتیجه مورد انتظار حاصل جمع (a, b)).

این describe برای سازماندهی بهتر، تابع تمام تست های مربوط به تابع مجموع را در یک بلوک واحد گروه بندی می کند.

در describe() بلوک کردن، it.each(dataset) روی هر ردیف در آرایه داده تکرار می شود.
"Sum of %d and %d should be %d" یک الگوی توضیحات برای آزمون است، که در آن %d در طول هر تکرار با اعداد واقعی از مجموعه داده جایگزین می شود.
به عنوان مثال، اولین تکرار این توصیف را ایجاد می کند: “مجموع 2 و 3 باید 5 باشد”.

در تابع callback (a, b, expected)، عناصر هر ردیف در مجموعه داده به متغیرهای a، b و انتظاری تخریب می شوند. سپس، در داخل آزمون، sum تابع با a و b فراخوانی می شود و نتیجه با استفاده از آن بررسی می شود expect() تا اطمینان حاصل شود که با انتظارات مطابقت دارد.

چرا استفاده کنید it.each() (یا test.each()

  • کارایی: به جای نوشتن جدا it() یا test() بلوک‌ها برای هر مورد، می‌توانید تمام موارد آزمایشی را در یک مجموعه داده تعریف کنید و از طریق آنها حلقه بزنید.
  • خوانایی: منطق تست مختصر است و مجموعه داده اضافه کردن یا اصلاح موارد تست را بدون تکرار کد آسان می کند.
  • مقیاس پذیری: هنگام برخورد با چندین مورد آزمایش مفید است، به خصوص زمانی که منطق مورد آزمایش در بین موارد مشابه است.

مثال عملی دیگر: محاسبه میانگین

برای نشان دادن یک مثال اضافی برای TDD، اجازه دهید یک تابع میانگین را در ماژول ماشین حساب پیاده سازی کنیم که میانگین (میانگین) آرایه ای از اعداد را محاسبه می کند. با پیروی از رویکرد TDD، با نوشتن تست ها شروع می کنیم.

در حال حاضر موجود calculator.test.js این تست های مخصوص را اضافه کنید mean() تابع:

const datasetForMean = [
  [ [ 1, 2, 3, 4, 5] ,  3],
  [ [],  null ],
  [ [ 42 ] , 42 ],
];
describe("mean function", () => {
  it.each(datasetForMean)("Mean of %p should be %p",
    (
      values,
      expected
    ) => {
    expect(mean(values)).toBe(expected);
  });
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در حال حاضر در calculator.ts فایل، اضافه کنید mean() تابع:

export function mean(data: number[]) {
  const count = data.length;
  if (count === 0) {
    return null;
  }
  const sum = data.reduce((total: number, num: number) => total + num, 0);
  return sum / count;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

bun test
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اجرای تست bun

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

پوشش تست

پوشش تست معیاری است که درصد اجرای کدهای شما را در طول تست های خودکار اندازه گیری می کند. بینش هایی را در مورد اینکه چقدر تست های شما کد شما را تایید می کند، ارائه می دهد.
پوشش تست Bun به شناسایی “پوشش خط” کمک می کند.
پوشش خط بررسی می کند که آیا هر خط کد در طول مجموعه آزمایشی اجرا شده است یا خیر.

اجرای پوشش تست:

bun test --coverage
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توضیحات تصویر

چرا پوشش مهم است؟

  • شناسایی شکاف‌ها در آزمایش‌ها: گزارش‌های پوشش مشخص می‌کنند که کدام بخش از کد شما آزمایش نشده است. این به شما کمک می کند تا مطمئن شوید که منطق انتقادی نادیده گرفته نمی شود.
  • بهبود کیفیت کد: پوشش بالا تضمین می کند که موارد لبه، مدیریت خطا و منطق تجاری به طور کامل آزمایش می شوند و احتمال بروز باگ را کاهش می دهد.
  • اطمینان در بازآفرینی: اگر یک پایگاه کد به خوبی آزمایش شده دارید، می توانید با اطمینان مجدداً اصلاح کنید، زیرا بدانید که آزمایش های شما رگرسیون ها را خواهند گرفت.
  • نگهداری بهتر: یک پایگاه کد با پوشش تست بالا نگهداری آسان‌تر است، زیرا می‌توانید تغییرات ناخواسته یا عوارض جانبی را در طول به‌روزرسانی تشخیص دهید.
  • از TDD پشتیبانی می کند: برای توسعه دهندگانی که توسعه تست محور را تمرین می کنند، پوشش نظارتی تضمین می کند که تست ها با پیاده سازی هماهنگ هستند.

متعادل کردن اهداف پوشش

در حالی که پوشش تست بالا مهم است، این تنها معیار کیفیت کد نیست. آزمایش‌های معنی‌داری را هدف قرار دهید که بر روی عملکرد، موارد لبه و بخش‌های حیاتی برنامه‌تان تمرکز دارند. دستیابی به پوشش 100% ایده آل است، اما نه به قیمت نوشتن تست های غیر ضروری یا پیش پا افتاده.

نتیجه گیری

توسعه تست محور (TDD) با تست Bun به توسعه دهندگان این امکان را می دهد تا با تمرکز بر الزامات ابتدا و اطمینان از عملکرد از طریق آزمایش تکراری، کدهای تمیز، قابل نگهداری و قوی بنویسند. با استفاده از ابزارهای تست سریع و کارآمد Bun، می توانید فرآیند توسعه خود را ساده کنید و با اطمینان موارد لبه را مدیریت کنید. اتخاذ TDD نه تنها کیفیت کد را بهبود می بخشد، بلکه ذهنیت نوشتن کد قابل آزمایش و مدولار را از همان ابتدا تقویت می کند. کوچک شروع کنید، مرتباً تکرار کنید و اجازه دهید آزمایش‌هایتان اجرای شما را راهنمایی کنند.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا