خلاصه: بسیاری از افراد هدف Cucumber را اشتباه میفهمند. از آنجا که به نظر میرسد Cucumber تست اسکریپتهایی با زبان ساده(Plain Language) ارائه می دهند، لذا تسترها تمایل دارند از Cucumber به عنوان ابزاری برای تست عمومی استفاده کنند، از جمله برای تستهای API. اما هدف واقعی آن به عنوان یک چارچوب BDD است. ممکن است فکر کنید، چه ضرری دارد؟ در اینجا دلیل تفاوت ذکر شده است و اینکه چرا شما باید ابزار دیگری را برای تست API انتخاب کنید.
Cucumber ابزاری برای توسعه رفتار محور(BDD) است که تستهایی را که به زبانی ساده و قابل فهم نوشته شدهاند، امکان پذیر میکند. هر یک از قسمتهای تست مشتمل بر حالت اولیه(Initial State)، اقدام(Action) و حالت متعاقب(Consequent State) آن، که در قالب سناریوی “Given-When-Then” ساخته میشوند، میتوانند به طور جداگانه موفقیت یا عدم موفقیت(یا در انتظار بودن) را تعیین کنند.
Cucumber در این شرایط خوب عمل می کند زیرا:
- معمولاً چند روز طول میکشد تا موفقیت در تست رخ دهد، زیرا تست طراحی کد را به پیش میبرد و ما میخواهیم پیشرفت خود را با موفقیت در سناریوها مشاهده کنیم(به عنوان مثال ، ممکن است عبارت “Given” را ببینیم اما عبارت “When” هنوز در انتظار است)
- Prose(نثر اولیه Business) از جلسه برنامهریزی(Planning Meeting) آغاز میشود، جایی که صاحب محصول(PO)، تستر و توسعه دهنده با انواع سناریوها که به عنوان نمونههای معتب، کامل و خودکار از ویژگی عمل میکنند، موافقت مینمایند.
- تستهای Prose-based، خوانندگان آینده را قادر میسازد تا دلایل مهم کسب و کار را درک کنند.
چنین چیزی قابلیتها را پوشش داده، امکان پیگیری(Traceability) بین نیازمندیها و کد، و نیز ایجاد “مستندات زنده” برای سیستم را مهیا میسازد. وقتی برنامهریزی روی ایجاد سناریوهایی از این نوع متمرکز است، منجر به همکاری بالاتر و درک مشترک بهتر میشود. در واقع، بسیاری از علاقمندان به BDD خواهند گفت که مهمترین بخش، بحث و ذهنیت منجر به کیفیت بالاتر است.
اینکه برای سناریوهای BDD، از APIها برای انجام کار آنها استفاده کنید خوب است. این اغلب یک رویکرد خوب است! اما API Testing تمرکز اصلی در این شرایط نیست.
API Testing در مقابل BDD
هنگامی که ما به طور خاص در مورد API Testing صحبت میکنیم، منظور ما پوشش مثبت و منفی نقاط انتهایی API است. در این حالت، ما معمولاً به پروتکل ارتباطی و Data Driven Testing در سطح تست Integration اهمیت میدهیم، یعنی یک URL شناخته شده داریم، برخی از دادهها را میفرستیم ، برخی از داده ها را دریافت کرده، و بررسی میکنیم تا به آنچه انتظار داریم برسیم. ما کاملاً به روش خاصی که با نقطه پایان(Endpint) ارتباط برقرار میکند، اهمیت میدهیم.
استفاده از Cucumber(یا چارچوب دیگر BDD) برای تست نقاط پایانی API غیر معمول نیست. با این حال، ویژگیهای Cucumber، مانند تست با استفاده از زبان ساده و استقلال مراحل در یک سناریو، واقعاً در مورد نیازهای تست Integration صدق نمیکند.
استفاده از زبان ساده ضروری نیست، زیرا برای درک نقطه پایانی API مهم نیست. جزئیات نحوه کار یک نقطه پایانی API اغلب بیشتر مربوط به جزئیات در سطح راهکار فنیست، تا تواناییهای کلان یا نیازهای کسب و کار.
این یک مساله دیدگاهیست. هنگام تست API روی چه چیزی متمرکز میشوید؟ اگر هدف ارائه پوشش در مورد نحوه کارکرد API باشد، معمولاً توجه به جزئیات فنی توجه میشود. مثلا اگر مقدار خالی برای [نام ، سن ، قد و غیره] ارسال شود، باید انتظار یک پیام خطا را داشته باشیم.
بعلاوه، استقلال بین عبارات “Given-When-Then” نیاز نمیشود، چرا که تست نقطه پایانی میتواند ایجاد شده و سریعا به صورت موفقیتآمیز پایان یابد.
از طرف دیگر، اگر شما با سرچشمه گرفتن از طریق API ها، در حال ایجاد Functionalityهای جدید هستید، استفاده از چارچوب BDD برای انجام این کار منطقی خواهد بود. اما باز هم معتقد نیستم چنین تستی، یک تست API است.
هنگام انجام تست API، نباید همه Functionalityهای اساسی را ایجاد کنیم. در عوض، باید بر ایجاد یک اینترفیس با کد از قبل ایجاد شده متمرکز شویم که با جزئیات گیج کننده پروتکلهای API سروکار دارد. آنهایی که تمایل دارند سریعاً تستها ایجاد و Pass شوند، اغلب به دنبال توسعه تست محور(TDD) هستند. به لحاظ عملی، از آنجا که میتوانیم در عرض چند دقیقه یا چند ساعت، تست را نوشته و آنرا Pass کنیم، نیازی به مستقل بودن مراحل نیست.
دیدگاه متفاوت
به عنوان مثال یک اپلیکیشن، Demo، پوشش سطوح مختلف تست را در روشهای گوناگون مهیا میکند.
برای سطح تست Acceptance که قابلیتگراست، از Cucumber برای پشتیبانی BDD استفاده میکنند. در این شرایط، ما نباید به یک فناوری خاص اهمیت دهیم بلکه باید برای قابلیت ارائه شده به مشتری ارزش قائل باشیم. به عنوان مثال، یک فروشنده آنلاین توانایی فروش کالاهایی را میخواهد. چگونگی انجام این کار نگرانی جداگانهای است، اما قابلیت اصلی فروش کالاست.
به طور جداگانه ، برای سطح Integration، مجموعهای از تستها با استفاده از چارچوب Pytest(در اصل، Python Unit Test Driver) در Python نوشته شده است که به سادگی دادهها را به یک Endpoint ارسال کرده و آنچه را که دریافت میدارد بررسی میکند(به test_api.py مراجعه کنید). در اینجاست که میخواهیم انبوهی از تستها را بنویسیم که همه روشهای بیشمار یک API Endpoint را از هر دو جنبه مثبت و منفی پوشش میدهد.
API Endpoint تمایل به ظرافت بیشتری دارند که برای دستیابی به پوشش بالا نیازمند تست قابل توجهی هستند.
یک جنبه دیگر که منحصر به تست API است(و متمایز از BDD) این است که پوشش، مربوط به تعداد زیادی از Endpointهاست که با آنها برخورد کردهایم. پوشش BDD همیشه باید در مورد قابلیت های کسب و کاری باشد. این دیدگاه دیگری است.
هدف واقعی Cucumber
معمولا در BDD میخواهید تا آنجا که ممکن است تستها کمی معطوف به یک فناوری باشد، مانند یک API خاص، یک قسمت خاص در یک صفحه یا یک دکمه خاص.
وقتی در BDD روی فناوری(و نه قابلیت) تمرکز میکنید، از چند طریق به تستها آسیب می رساند:
- فناوری اغلب تغییر میکند. ولی قابلیتها تقریباً اغلب تغییر نمیکنند. هرچه بهتر تستهای خود را به جنبههای تغییرناپذیر گره بزنید(مانند قابلیتها)، به نگهداشت(Maintenance) کمتری نیاز خواهید داشت.
- Prose به عنوان سندی برای قابلیتهای سیستم شما عمل میکند و باید برای همه شرکا دسترسپذیر باشد(به ویژه شرکای کسب و کاری. البته درک دلایل کسب و کاری برای افراد فنی نیز مهم است).
- به طور عملی، تستهای Cucumber برای کار کردن کمی دشوارتر از تستهای یونیت هستند. آنها State را با مقادیر کلاس(Class Variable)، میان متدها حمل میکنند. بسیاری از IDEها توانایی کمی در دیباگ آنها دارند، و این میتواند موضوع نگهداشت مجموعه نگاشت prose به کد را پیچیده کند.
بسیاری از افراد هدف Cucumber را اشتباه میفهمند. یک الگوی رایج که امیدوارم کمتر شاهد آن باشم، استفاده از Cucumber به عنوان یک وسیله تست عمومیست، چرا که به نظر میرسد تست اسکریپتهای واضح و ساده ارائه میدهد.
تسترها به طور قابل توجهی مشتاق تست اسکریپتهایی هستند که بهتر ماهیت و چرایی آنچه که تست میشود را تشریح میکنند. با این حال، یک دام پنهان وجود دارد.
نوشتن تستهای Cucumber مستلزم ایجاد کد چسب یا Glue Code است. کد چسب در برنامه نویسی کامپیوتری، یک کد اجراییست که صرفاً برای “سازگاری” بخشهای مختلف کد استفاده میشود، که بدون وجود آن این بخشها ناسازگار خواهند شد. کد چسب هیچ عملکردی را که در جهت برآورده کردن نیازهای برنامه است تامین میکند. در اینجا کد چسب، Prose انگلیسی را با استفاده از عبارات منظم به کد واقعی پیوند میدهد. هنگامی که قابلیتها را تست میکنید، ایجاد این کد چسب هزینه کم هزینه مینماید، اما اگر هدف شما تست همه جزئیات ریز و در مقیاس کوچک است، بسیار گران خواهد شد. کد چسب یک کد اضافی برای نوشتن و نگهداریست که به راحتی میتواند منبع قطع ارتباط باشد(مانند زمانی که نویسنده کد چسب واقعاً متوجه نیست که چه چیزی در Prose مورد نظر است).
در نهایت، Cucumber یک چارچوب BDD است و باید فقط برای پشتیبانی از BDD استفاده شود. تست API بر پوشش API Endpoint متمرکز است و بر خلاف تست BDD که بیشتر معطوف به قابلیتهای کسب و کاریست، اکثرا به دنبال راهکار فنیست.
حتی اگر وسوسه انگیز هم باشد، شما باید برای تست API خود ابزاری غیر از Cucumber انتخاب کنید.