توسعه API مبتنی بر آزمایش در Go

Summarize this content to 400 words in Persian Lang
معرفی
توسعه آزمایش محور یک روش موثر برای اطمینان از کدهای آزمایش شده و قابل بازیابی است. ایده اصلی این است که توسعه را با نوشتن تست ها شروع کنید. این تستها به وضوح انتظارات را مستند میکنند و یک روبریک برای اجرای موفق ایجاد میکنند. هنگامی که به درستی انجام شود، می توانید قبل از نوشتن هر کد، ورودی/خروجی مورد انتظار یک تابع را به وضوح تعریف کنید. این چند فواید فوری دارد:
شما با دقت رابطی را برای تعامل با کد خود در نظر می گیرید و آن را قابل آزمایش طراحی می کنید
وقتی شروع به نوشتن کد می کنید، جریان شما با آزمایش دستی یا قدم گذاشتن در منطق اجرا برای پیش بینی نتیجه قطع نمی شود. در عوض، شما فقط تست ها را اجرا می کنید
قبولی در آزمون به هدفی تبدیل می شود که رسیدن به آن رضایت بخش است. تقسیم فرآیند به مجموعه ای از نقاط عطف به خوبی تعریف شده و قابل دستیابی، کار را لذت بخش تر می کند.
از تنبلی و اعتماد بیش از حد پس از پیاده سازی که می تواند مانع از آزمایش کد شما شود، اجتناب کنید
اکنون که از مزایا متقاعد شدید، میتوانید با دنبال کردن این مراحل، توسعه آزمایش محور (TDD) را شروع کنید:
تست ها را بنویسید یا اصلاح کنید
بررسی کنید که آیا تست شکست خورده است
حداقل مقدار کد را بنویسید تا آزمون ها قبول شوند
این مراحل در یک چرخه دنبال میشوند، بنابراین شما همیشه آزمایشهای بیشتری را برای به چالش کشیدن اجرای فعلی اضافه میکنید.
آخرین مرحله، که نوشتن حداقل مقدار کد را مشخص میکند، جایی است که در صورت پیگیری دقیق، همه چیز خستهکننده میشود. قبل از اینکه بتوانید تشخیص دهید چه زمانی مناسب است که از آن دور شوید، درک اینکه چرا این قانون وجود دارد، مهم است.
مثال ساده
شما وظیفه اجرای تابع را دارید Add(x, y int) int. قبل از اینکه به اجرای و فقط بپرید return x + y، ساده ترین تست را بنویسید: 1 + 1 == 2. سپس، سادهترین پیادهسازی که میتواند آزمون را با موفقیت پشت سر بگذارد چیست؟ این فقط return 2. حالا تست های شما قبول می شود!
در این مرحله، متوجه میشوید که به آزمایشهای بیشتری نیاز دارید، بنابراین سرعت را بالا میبرید و چند مورد دیگر را اضافه میکنید:
1 + 2 == 3
100 + 5 == 105
اکنون تست های شما با شکست مواجه می شوند، بنابراین باید پیاده سازی را برطرف کنید. شما نمی توانید فقط return 3 یا return 105 این بار، بنابراین شما باید راه حلی پیدا کنید که برای همه آزمایش ها کار کند. این منجر به پیاده سازی می شود: return x + y.
در حالی که این در مثال بی اهمیت بیش از حد خسته کننده به نظر می رسد، پیروی دقیق از این روش باعث می شود به جای اعتماد به پیاده سازی خود، چندین تست بنویسید. البته ایده اولیه شما به return x + y کار می کرد، اما نکته این است که خود را دوباره آموزش دهید تا به جای درک خود از کد، به تست ها تکیه کنید. در دنیای واقعی، شما تنها کسی نیستید که روی این قطعه کد کار می کنید و به ناچار جزئیات پیاده سازی را فراموش خواهید کرد. این فرآیند شما را مجبور میکند تا تستهای بیشتری بنویسید و به راههای بیشتری برای شکستن اجرای ساده فکر کنید.
در نهایت، تجربه کسب خواهید کرد و یاد خواهید گرفت که تعادلی را پیدا کنید که در سناریوهای مختلفی که با آن مواجه می شوید کارآمد باشد. به اجرای کامل ویژگیها برمیگردید و متوجه میشوید که اشکالات کمتری دارید و کدهای قابل نگهداری بیشتری مینویسید.
TDD گام به گام برای یک API HTTP
بیایید با استفاده از TDD برای HTTP REST API به مثال پیچیدهتری بپردازیم. این راهنمای گام به گام از چارچوب Go من استفاده می کند، babyapi، اما مفاهیم را می توان در هر جایی اعمال کرد.
babyapi از ژنریک ها برای ایجاد یک CRUD API کامل در اطراف ساختارهای Go استفاده می کند و ایجاد یک REST API کامل و CLI مشتری را بسیار آسان می کند. علاوه بر این، babytest بسته برخی از ابزارها را برای ایجاد آزمونهای جداول API سرتاسر فراهم میکند. استفاده از TDD در سطح API امکان آزمایش کامل HTTP و لایه های ذخیره سازی یک API یا ویژگی جدید را به یکباره می دهد.
سلب مسئولیت: از آنجا که babyapi بیشتر پیاده سازی را انجام می دهد و همچنین برای تولید دیگ بخار آزمایشی استفاده می شود، ما از نظر فنی با TDD شروع نمی کنیم. با این حال، هنگام اضافه کردن پشتیبانی، خواهیم دید که چقدر سودمند است PATCH درخواست ها به API ما.
یک پروژه Go جدید ایجاد کنید
ایجاد اولیه main.go استفاده كردن babyapiمثال ساده
از CLI برای تولید یک دیگ بخار آزمایشی استفاده کنید
هر آزمایش را با پر کردن مکانها با JSON مورد انتظار اجرا کنید
تست ها را اجرا کنید و ببینید که آنها قبول می شوند!
از آنجا که PUT ناتوان است، نیاز به گنجاندن همه فیلدها دارد. برای جلوگیری از این امر، میخواهیم پشتیبانی برای جابجایی اضافه کنیم Completed با PATCH درخواست ها. ما با اضافه کردن یک آزمایش ساده برای اینکه انتظار داریم این ویژگی چگونه باشد، شروع می کنیم
این آزمون از آن زمان ناموفق است babyapi پشتیبانی نمی کند PATCH به صورت پیش فرض. می توانیم با پیاده سازی آن را رفع کنیم Patch برای TODO ساخت. از آنجایی که ما ویژگی خود را با دو تست تعریف کردیم، ساده ترین پیاده سازی ما فقط تنظیم نیست Completed = true و باید از مقدار درخواست استفاده کنیم
حالا ما می توانیم تغییر دهیم Completed وضعیت الف TODO، اما هنوز نمی توانیم استفاده کنیم PATCH برای اصلاح سایر فیلدها همانطور که در این مجموعه آزمایشی جدید نشان داده شده است
به روز رسانی Patch برای تنظیم فیلدهای باقی مانده
تستهای ما همچنان با شکست مواجه میشوند، زیرا ما همیشه آن را بهروزرسانی میکنیم TODO با فیلدهای درخواست، حتی اگر خالی باشند. این مشکل را با بهروزرسانی پیادهسازی برای بررسی مقادیر خالی برطرف کنید
جدید UpdateWithPatch آزمون قبول می شود، اما آزمون های قبلی ما شکست می خورند. از وقتی عوض شدیم Completed بودن *bool، TODOs ایجاد شده با مقدار خالی به صورت نمایش داده می شود null
پیاده سازی Render برای TODO تا بتوانیم درمان کنیم nil مانند false
پیاده سازی PATCH ویژگی با توسعه آزمایش محور منجر به مجموعه ای قوی از تست ها و یک ویژگی به خوبی پیاده سازی شده است. از آنجایی که ما با تعریف ورودی و خروجی مورد انتظار a شروع کردیم PATCH درخواست در تستها، مشاهده مشکلات ناشی از عدم بررسی مقادیر خالی در درخواست آسان بود. همچنین، آزمایشهای قبلی ما توانستند هنگام تغییر نوع، از تغییرات شکسته محافظت کنند Completed به *bool.
نتیجه
توسعه تست محور یک رویکرد موثر برای ایجاد کد کاملاً آزمایش شده و صحیح است. با شروع با در نظر گرفتن تستها، میتوانیم اطمینان حاصل کنیم که هر قطعه کد بهجای اینکه اجازه دهیم تستها یک فکر بعدی باشند، به گونهای طراحی شده است که قابل آزمایش باشد.
اگر در مورد پذیرش TDD مردد هستید، در اینجا چند ایده برای شروع وجود دارد:
آن را در سناریوهای ساده ای که ورودی/خروجی یک تابع واضح است و اجرای آن بیش از حد پیچیده نیست، امتحان کنید. شما می توانید یک تست جدول قوی برای انواع ورودی/خروجی که ممکن است با آن مواجه شوید بنویسید. داشتن تصویری واضح از سناریوهای مختلف می تواند اجرا را ساده کند
اگر در حال رفع یک باگ جدید هستید، قبلاً شکافی را در آزمایش خود شناسایی کرده اید. با نوشتن تستی شروع کنید که در وهله اول این اشکال را شناسایی کند. سپس، این آزمون را بدون شکستن تست های موجود قبول کنید.
شبیه به babyapi به عنوان مثال، می توانید از TDD برای تست های API سطح بالا استفاده کنید. هنگامی که تعریفی از درخواست/پاسخ مورد انتظار داشتید، می توانید جریان توسعه معمول خود را برای بخش های جزئیات گرا از پیاده سازی از سر بگیرید.
حتی اگر TDD برای نحوه نوشتن کد مناسب نباشد، باز هم ابزار قدرتمندی است که در کمربند شما وجود دارد. من شما را تشویق میکنم که حداقل زمانی را برای امتحان کردن آن اختصاص دهید و ببینید که چگونه بر روند توسعه شما تأثیر میگذارد.
معرفی
توسعه آزمایش محور یک روش موثر برای اطمینان از کدهای آزمایش شده و قابل بازیابی است. ایده اصلی این است که توسعه را با نوشتن تست ها شروع کنید. این تستها به وضوح انتظارات را مستند میکنند و یک روبریک برای اجرای موفق ایجاد میکنند. هنگامی که به درستی انجام شود، می توانید قبل از نوشتن هر کد، ورودی/خروجی مورد انتظار یک تابع را به وضوح تعریف کنید. این چند فواید فوری دارد:
- شما با دقت رابطی را برای تعامل با کد خود در نظر می گیرید و آن را قابل آزمایش طراحی می کنید
- وقتی شروع به نوشتن کد می کنید، جریان شما با آزمایش دستی یا قدم گذاشتن در منطق اجرا برای پیش بینی نتیجه قطع نمی شود. در عوض، شما فقط تست ها را اجرا می کنید
- قبولی در آزمون به هدفی تبدیل می شود که رسیدن به آن رضایت بخش است. تقسیم فرآیند به مجموعه ای از نقاط عطف به خوبی تعریف شده و قابل دستیابی، کار را لذت بخش تر می کند.
- از تنبلی و اعتماد بیش از حد پس از پیاده سازی که می تواند مانع از آزمایش کد شما شود، اجتناب کنید
اکنون که از مزایا متقاعد شدید، میتوانید با دنبال کردن این مراحل، توسعه آزمایش محور (TDD) را شروع کنید:
- تست ها را بنویسید یا اصلاح کنید
- بررسی کنید که آیا تست شکست خورده است
- حداقل مقدار کد را بنویسید تا آزمون ها قبول شوند
این مراحل در یک چرخه دنبال میشوند، بنابراین شما همیشه آزمایشهای بیشتری را برای به چالش کشیدن اجرای فعلی اضافه میکنید.
آخرین مرحله، که نوشتن حداقل مقدار کد را مشخص میکند، جایی است که در صورت پیگیری دقیق، همه چیز خستهکننده میشود. قبل از اینکه بتوانید تشخیص دهید چه زمانی مناسب است که از آن دور شوید، درک اینکه چرا این قانون وجود دارد، مهم است.
مثال ساده
شما وظیفه اجرای تابع را دارید Add(x, y int) int
. قبل از اینکه به اجرای و فقط بپرید return x + y
، ساده ترین تست را بنویسید: 1 + 1 == 2
. سپس، سادهترین پیادهسازی که میتواند آزمون را با موفقیت پشت سر بگذارد چیست؟ این فقط return 2
. حالا تست های شما قبول می شود!
در این مرحله، متوجه میشوید که به آزمایشهای بیشتری نیاز دارید، بنابراین سرعت را بالا میبرید و چند مورد دیگر را اضافه میکنید:
1 + 2 == 3
100 + 5 == 105
اکنون تست های شما با شکست مواجه می شوند، بنابراین باید پیاده سازی را برطرف کنید. شما نمی توانید فقط return 3
یا return 105
این بار، بنابراین شما باید راه حلی پیدا کنید که برای همه آزمایش ها کار کند. این منجر به پیاده سازی می شود: return x + y
.
در حالی که این در مثال بی اهمیت بیش از حد خسته کننده به نظر می رسد، پیروی دقیق از این روش باعث می شود به جای اعتماد به پیاده سازی خود، چندین تست بنویسید. البته ایده اولیه شما به return x + y
کار می کرد، اما نکته این است که خود را دوباره آموزش دهید تا به جای درک خود از کد، به تست ها تکیه کنید. در دنیای واقعی، شما تنها کسی نیستید که روی این قطعه کد کار می کنید و به ناچار جزئیات پیاده سازی را فراموش خواهید کرد. این فرآیند شما را مجبور میکند تا تستهای بیشتری بنویسید و به راههای بیشتری برای شکستن اجرای ساده فکر کنید.
در نهایت، تجربه کسب خواهید کرد و یاد خواهید گرفت که تعادلی را پیدا کنید که در سناریوهای مختلفی که با آن مواجه می شوید کارآمد باشد. به اجرای کامل ویژگیها برمیگردید و متوجه میشوید که اشکالات کمتری دارید و کدهای قابل نگهداری بیشتری مینویسید.
TDD گام به گام برای یک API HTTP
بیایید با استفاده از TDD برای HTTP REST API به مثال پیچیدهتری بپردازیم. این راهنمای گام به گام از چارچوب Go من استفاده می کند، babyapi
، اما مفاهیم را می توان در هر جایی اعمال کرد.
babyapi
از ژنریک ها برای ایجاد یک CRUD API کامل در اطراف ساختارهای Go استفاده می کند و ایجاد یک REST API کامل و CLI مشتری را بسیار آسان می کند. علاوه بر این، babytest
بسته برخی از ابزارها را برای ایجاد آزمونهای جداول API سرتاسر فراهم میکند. استفاده از TDD در سطح API امکان آزمایش کامل HTTP و لایه های ذخیره سازی یک API یا ویژگی جدید را به یکباره می دهد.
سلب مسئولیت: از آنجا که babyapi
بیشتر پیاده سازی را انجام می دهد و همچنین برای تولید دیگ بخار آزمایشی استفاده می شود، ما از نظر فنی با TDD شروع نمی کنیم. با این حال، هنگام اضافه کردن پشتیبانی، خواهیم دید که چقدر سودمند است PATCH
درخواست ها به API ما.
-
یک پروژه Go جدید ایجاد کنید
-
ایجاد اولیه
main.go
استفاده كردنbabyapi
مثال ساده -
از CLI برای تولید یک دیگ بخار آزمایشی استفاده کنید
-
هر آزمایش را با پر کردن مکانها با JSON مورد انتظار اجرا کنید
-
تست ها را اجرا کنید و ببینید که آنها قبول می شوند!
-
از آنجا که
PUT
ناتوان است، نیاز به گنجاندن همه فیلدها دارد. برای جلوگیری از این امر، میخواهیم پشتیبانی برای جابجایی اضافه کنیمCompleted
باPATCH
درخواست ها. ما با اضافه کردن یک آزمایش ساده برای اینکه انتظار داریم این ویژگی چگونه باشد، شروع می کنیم -
این آزمون از آن زمان ناموفق است
babyapi
پشتیبانی نمی کندPATCH
به صورت پیش فرض. می توانیم با پیاده سازی آن را رفع کنیمPatch
برایTODO
ساخت. از آنجایی که ما ویژگی خود را با دو تست تعریف کردیم، ساده ترین پیاده سازی ما فقط تنظیم نیستCompleted = true
و باید از مقدار درخواست استفاده کنیم -
حالا ما می توانیم تغییر دهیم
Completed
وضعیت الفTODO
، اما هنوز نمی توانیم استفاده کنیمPATCH
برای اصلاح سایر فیلدها همانطور که در این مجموعه آزمایشی جدید نشان داده شده است -
به روز رسانی
Patch
برای تنظیم فیلدهای باقی مانده -
تستهای ما همچنان با شکست مواجه میشوند، زیرا ما همیشه آن را بهروزرسانی میکنیم
TODO
با فیلدهای درخواست، حتی اگر خالی باشند. این مشکل را با بهروزرسانی پیادهسازی برای بررسی مقادیر خالی برطرف کنید -
جدید
UpdateWithPatch
آزمون قبول می شود، اما آزمون های قبلی ما شکست می خورند. از وقتی عوض شدیمCompleted
بودن*bool
،TODO
s ایجاد شده با مقدار خالی به صورت نمایش داده می شودnull
-
پیاده سازی
Render
برایTODO
تا بتوانیم درمان کنیمnil
مانندfalse
پیاده سازی PATCH
ویژگی با توسعه آزمایش محور منجر به مجموعه ای قوی از تست ها و یک ویژگی به خوبی پیاده سازی شده است. از آنجایی که ما با تعریف ورودی و خروجی مورد انتظار a شروع کردیم PATCH
درخواست در تستها، مشاهده مشکلات ناشی از عدم بررسی مقادیر خالی در درخواست آسان بود. همچنین، آزمایشهای قبلی ما توانستند هنگام تغییر نوع، از تغییرات شکسته محافظت کنند Completed
به *bool
.
نتیجه
توسعه تست محور یک رویکرد موثر برای ایجاد کد کاملاً آزمایش شده و صحیح است. با شروع با در نظر گرفتن تستها، میتوانیم اطمینان حاصل کنیم که هر قطعه کد بهجای اینکه اجازه دهیم تستها یک فکر بعدی باشند، به گونهای طراحی شده است که قابل آزمایش باشد.
اگر در مورد پذیرش TDD مردد هستید، در اینجا چند ایده برای شروع وجود دارد:
- آن را در سناریوهای ساده ای که ورودی/خروجی یک تابع واضح است و اجرای آن بیش از حد پیچیده نیست، امتحان کنید. شما می توانید یک تست جدول قوی برای انواع ورودی/خروجی که ممکن است با آن مواجه شوید بنویسید. داشتن تصویری واضح از سناریوهای مختلف می تواند اجرا را ساده کند
- اگر در حال رفع یک باگ جدید هستید، قبلاً شکافی را در آزمایش خود شناسایی کرده اید. با نوشتن تستی شروع کنید که در وهله اول این اشکال را شناسایی کند. سپس، این آزمون را بدون شکستن تست های موجود قبول کنید.
- شبیه به
babyapi
به عنوان مثال، می توانید از TDD برای تست های API سطح بالا استفاده کنید. هنگامی که تعریفی از درخواست/پاسخ مورد انتظار داشتید، می توانید جریان توسعه معمول خود را برای بخش های جزئیات گرا از پیاده سازی از سر بگیرید.
حتی اگر TDD برای نحوه نوشتن کد مناسب نباشد، باز هم ابزار قدرتمندی است که در کمربند شما وجود دارد. من شما را تشویق میکنم که حداقل زمانی را برای امتحان کردن آن اختصاص دهید و ببینید که چگونه بر روند توسعه شما تأثیر میگذارد.