علیرضا کیماسی
علیرضا کیماسی
خواندن ۳ دقیقه·۵ ماه پیش

اهمیت Readability و نام‌گذاری تست‌ها در Unit Test


در دنیای برنامه‌نویسی، رویکرد Test Driven Development (TDD) و نوشتن Unit Test ها اهمیت بسیاری دارد. اما چرا اینقدر به خوانایی تست‌ها تاکید می‌شود؟

در این مقاله به بررسی اهمیت خوانایی در تست‌های واحد و تأثیر آن در توسعه نرم‌افزار می‌پردازیم.

چرا خوانایی در تست‌ها مهم است؟

خوانایی تست‌ها به این معناست که هر کسی که کد شما را می‌خواند، بتواند به سادگی بفهمد که چه چیزی تست می‌شود و چه انتظاری از آن تست داریم. این ویژگی اهمیت بالایی دارد زیرا:

  1. مستندسازی زنده (Living Documentation): تست‌های خوانا می‌توانند به عنوان مستندات زنده عمل کنند. این مستندات به روز و همگام با کد تغییر می‌کنند و نیازی به مستندات سنتی را کاهش می‌دهند.
  2. پیدا کردن سریع باگ‌ها (Defect Localization): تست‌های خوانا کمک می‌کنند تا محل دقیق باگ‌ها سریع‌تر شناسایی شود. این موضوع به ویژه زمانی اهمیت دارد که پیدا کردن محل وقوع باگ دشوارتر از رفع آن باشد.

ویژگی‌های تست‌های خوب

تست‌های واحد باید سه ویژگی مهم داشته باشند: قابل نگهداری (Maintainability)، قابل اطمینان (Trustworthy) و خوانا بودن (Readability). از این میان، Readability مهم‌ترین ویژگی است .

مفهوم مستندسازی زنده

مستندسازی زنده به این معناست که تست‌های ما باید عملکرد سیستم را به صورت واضح بیان کنند. این تست‌ها همراه با تغییرات کد، به روز می‌شوند و به عنوان مستندات زنده عمل می‌کنند.

مفهوم پیدا کردن سریع باگ‌ها

پیدا کردن محل دقیق باگ‌ها در کوتاه‌ترین زمان ممکن از اهمیت بالایی برخوردار است. تست‌های خوب می‌توانند این کار را با شناسایی سریع مکان وقوع باگ‌ها انجام دهند.

انتخاب نام مناسب برای تست‌ها

انتخاب نام مناسب برای تست‌ها نقش مهمی در افزایش خوانایی آن‌ها دارد. به تست زیر دقت کنید:

[Fact] public void TestConstructorFailure() { // Arrange const string name = null; const int health = 100; const int damage = 10; // Assert Assert.Throws<NullReferenceException>(() => new Hero(name, health, damage)); }

در نگاه اول از نام این تست نمی‌توان فهمید که چه چیزی تحت تست است.

با استفاده از یک الگوی نام‌گذاری مناسب، می‌توان خوانایی تست را بهبود بخشید:

[Fact] public void Constructor_ShouldThrowException_WhenNameIsNull() { // Arrange const string name = null; const int health = 100; const int damage = 10; // Assert Assert.Throws<NullReferenceException>(() => new Hero(name, health, damage)); }

با این تغییر، حالا کاملاً مشخص است که این تست چه چیزی را بررسی می‌کند.

الگوهای نام‌گذاری تست‌ها

الگوهای متعددی برای نام‌گذاری تست‌ها وجود دارد که برخی از آن‌ها به شرح زیر است:

  1. MethodName_StateUnderTest_ExpectedBehavior: این الگو بیانگر متد تحت تست، حالت تست و رفتار مورد انتظار است.

مثال: isAdult_AgeLessThan18_False

  1. Should_ExpectedBehavior_When_StateUnderTest: این الگو تاکید می‌کند که در چه حالتی چه رفتاری باید رخ دهد.

مثال: Should_ThrowException_When_AgeLessThan18

  1. Given_Preconditions_When_StateUnderTest_Then_ExpectedBehavior: این الگو در توسعه مبتنی بر رفتار (BDD) استفاده می‌شود و مراحل مختلف تست را توصیف می‌کند.

مثال: Given_UserIsAuthenticated_When_InvalidAccountNumberIsUsedToWithdrawMoney_Then_TransactionsWillFail

ساختار بدنه تست‌ها

ساختار بدنه تست‌ها باید به گونه‌ای باشد که قابل فهم و نگهداری باشد. یکی از روش‌های متداول برای ساختاردهی تست‌ها استفاده از الگوی (Arrange, Act, Assert) است:

  • Arrange: تنظیم وابستگی‌های تست (موک‌ها و متغیرها).
  • Act: فراخوانی متدهای شیء تست و دریافت خروجی در صورت وجود.
  • Assert: بررسی خروجی و اطمینان از صحت عملکرد تست.

نتیجه‌گیری

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

unit testclean codeتست نویسی در برنامه نویسیtddbdd
یه برنامه نویس معمولی ...
شاید از این پست‌ها خوشتان بیاید