در دنیای پویای توسعه نرم‌افزار، سرعت و کیفیت دو بال موفقیت محسوب می‌شوند. تیم‌های توسعه همواره در تلاشند تا با حفظ کیفیت، سرعت تحویل محصول را افزایش دهند. یکی از کلیدی‌ترین راهکارها برای دستیابی به این هدف، پیاده‌سازی فرآیندهای یکپارچه‌سازی و تحویل مداوم (CI/CD) به همراه تست‌های خودکار است. GitLab CI، به عنوان یکی از ابزارهای قدرتمند در این حوزه، امکانات وسیعی را برای خودکارسازی فرآیند تست و ادغام آن در چرخه توسعه نرم‌افزار فراهم می‌کند. این مقاله به عنوان یک راهنمای جامع، شما را گام به گام با فرآیند ادغام تست‌های خودکار در GitLab CI آشنا خواهد کرد.

چرا ادغام تست‌های خودکار با GitLab CI حیاتی است؟

پیش از ورود به جزئیات فنی، درک اهمیت این موضوع ضروری است. ادغام تست‌های خودکار در پایپ‌لاین CI/CD مزایای متعددی را به همراه دارد:

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

پیش‌نیازها برای شروع

برای دنبال کردن این راهنما، به موارد زیر نیاز خواهید داشت:

  • یک حساب کاربری در GitLab (می‌تواند GitLab.com یا یک نمونه خودمیزبان باشد).
  • یک پروژه در GitLab که می‌خواهید تست‌های خودکار را برای آن پیکربندی کنید.
  • آشنایی اولیه با مفاهیم Git و فرآیندهای CI/CD.
  • دانش پایه در مورد نوع تست‌هایی که قصد اجرای آن‌ها را دارید (مثلاً تست واحد، تست یکپارچه‌سازی).
  • تست‌های خودکار نوشته شده برای پروژه شما (برای مثال با استفاده از فریمورک‌هایی مانند JUnit برای جاوا، PyTest یا Unittest برای پایتون، Jest یا Mocha برای جاوااسکریپت و غیره).

آشنایی با مفاهیم کلیدی GitLab CI

قبل از پیکربندی، بیایید با برخی از مفاهیم اصلی در GitLab CI آشنا شویم:

  • .gitlab-ci.yml: این فایل قلب تپنده GitLab CI است. یک فایل با فرمت YAML که در ریشه پروژه شما قرار می‌گیرد و نحوه ساخت، تست و استقرار برنامه شما را تعریف می‌کند.
  • Pipeline (پایپ‌لاین): مجموعه‌ای از مراحل (Stages) و کارها (Jobs) که به ترتیب خاصی اجرا می‌شوند. هر بار که کدی به مخزن Push می‌شود (یا بر اساس تریگرهای دیگر)، یک پایپ‌لاین جدید ایجاد و اجرا می‌شود.
  • Stages (مراحل): پایپ‌لاین‌ها به مراحل مختلفی تقسیم می‌شوند (مثلاً buildtestdeploy). کارها در یک مرحله به صورت موازی اجرا می‌شوند (اگر منابع کافی وجود داشته باشد) و تنها در صورت موفقیت تمامی کارهای یک مرحله، مرحله بعدی آغاز می‌شود.
  • Jobs (کارها): دستورالعمل‌های مشخصی هستند که در یک Runner اجرا می‌شوند. هر کار شامل اسکریپت‌هایی است که باید اجرا شوند (مثلاً کامپایل کد، اجرای تست‌ها).
  • Runners (اجراکنندگان): ماشین‌ها (فیزیکی یا مجازی) هستند که پایپ‌لاین‌های CI/CD شما را اجرا می‌کنند. GitLab انواع مختلفی از Runnerها را ارائه می‌دهد:
    • Shared Runners: توسط GitLab مدیریت شده و برای تمامی پروژه‌ها در GitLab.com در دسترس هستند.
    • Specific Runners: توسط شما برای پروژه‌های خاصی راه‌اندازی و مدیریت می‌شوند.
    • Group Runners: برای تمامی پروژه‌های یک گروه خاص در دسترس هستند.
  • Artifacts (مصنوعات): فایل‌ها یا دایرکتوری‌هایی هستند که توسط یک کار تولید می‌شوند و می‌توانند برای استفاده در کارهای بعدی در همان پایپ‌لاین (یا برای دانلود) ذخیره شوند. گزارش‌های تست و فایل‌های پوشش کد (Code Coverage) نمونه‌هایی از مصنوعات هستند.

انواع تست‌های خودکار قابل ادغام

می‌توانید انواع مختلفی از تست‌های خودکار را در پایپ‌لاین GitLab CI خود ادغام کنید:

  • تست‌های واحد (Unit Tests): کوچکترین بخش‌های کد (مانند توابع یا متدها) را به صورت مجزا تست می‌کنند. سرعت اجرای بالایی دارند و برای شناسایی سریع خطاها در منطق کد بسیار مفیدند.
  • تست‌های یکپارچه‌سازی (Integration Tests): تعامل بین چند جزء یا ماژول از سیستم را بررسی می‌کنند. هدف آن‌ها اطمینان از صحت عملکرد اجزای مختلف در کنار یکدیگر است.
  • تست‌های سرتاسری (End-to-End Tests یا E2E Tests): کل جریان کاری یک برنامه را از دید کاربر نهایی شبیه‌سازی می‌کنند. این تست‌ها پیچیده‌تر و زمان‌برتر هستند اما دید جامعی از عملکرد سیستم ارائه می‌دهند.
  • تست‌های عملکرد (Performance Tests): سرعت، پایداری و پاسخگویی برنامه تحت بار کاری مشخص را ارزیابی می‌کنند.
  • تست‌های امنیت (Security Tests): آسیب‌پذیری‌های امنیتی برنامه را شناسایی می‌کنند.

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

راهنمای گام به گام ادغام تست‌های خودکار در GitLab CI

اکنون که با مفاهیم پایه آشنا شدیم، بیایید مراحل عملی ادغام تست‌ها را بررسی کنیم.

گام ۱: آماده‌سازی پروژه و تست‌ها

اطمینان حاصل کنید که پروژه شما در GitLab موجود است و تست‌های خودکار برای آن نوشته شده‌اند. دستورات لازم برای اجرای این تست‌ها از طریق خط فرمان (CLI) باید مشخص باشند. به عنوان مثال، اگر از پایتون و PyTest استفاده می‌کنید، دستور معمول pytest است، یا برای یک پروژه Node.js با Jest، دستور npm test یا yarn test خواهد بود.

گام ۲: ایجاد فایل .gitlab-ci.yml

در ریشه پروژه خود، یک فایل جدید با نام .gitlab-ci.yml ایجاد کنید. این فایل جایی است که شما پایپ‌لاین CI/CD خود را تعریف خواهید کرد.

گام ۳: تعریف مراحل (Stages)

ابتدا، مراحل پایپ‌لاین خود را تعریف کنید. یک ترتیب معمول می‌تواند شامل مراحل ساخت، تست و استقرار باشد.

stages:
  - build
  - test
  - deploy # این مرحله فعلاً اختیاری است و می‌توان بعداً اضافه کرد

گام ۴: ایجاد کار (Job) برای اجرای تست‌ها

حالا یک کار جدید برای اجرای تست‌های خودکار در مرحله test تعریف می‌کنیم. در این مثال، فرض می‌کنیم که پروژه ما یک برنامه پایتون است و از pytest برای تست استفاده می‌کند.

stages:
  - build # ممکن است برای پروژه شما مرحله build لازم باشد
  - test

# مثال کار برای یک پروژه پایتون
python_tests:
  stage: test
  image: python:3.9 # استفاده از یک ایمیج داکر با پایتون نسخه ۳.۹
  before_script:
    - pip install -r requirements.txt # نصب وابستگی‌ها، شامل pytest
  script:
    - pytest --junitxml=report.xml # اجرای تست‌ها و تولید گزارش در فرمت JUnit XML
  artifacts:
    when: always # همیشه مصنوعات را جمع‌آوری کن، حتی اگر کار شکست بخورد
    reports:
      junit: report.xml # مشخص کردن مسیر گزارش تست برای نمایش در GitLab UI
    paths:
      - report.xml # ذخیره فایل گزارش به عنوان مصنوع
      # - htmlcov/ # اگر گزارش پوشش کد HTML دارید، آن را نیز اضافه کنید

توضیح بخش‌های مختلف کار python_tests:

  • stage: test: مشخص می‌کند که این کار به مرحله test تعلق دارد.
  • image: python:3.9: ایمیج داکری که برای اجرای این کار استفاده خواهد شد. شما باید ایمیجی را انتخاب کنید که محیط مناسب برای اجرای تست‌های شما را فراهم کند (مثلاً node:16 برای پروژه‌های Node.js).
  • before_script: دستوراتی که قبل از اجرای اسکریپت اصلی (script) اجرا می‌شوند. معمولاً برای نصب وابستگی‌ها یا آماده‌سازی محیط استفاده می‌شود.
  • script: دستورات اصلی که برای اجرای تست‌ها استفاده می‌شوند. در اینجا، pytest --junitxml=report.xml تست‌ها را اجرا کرده و نتایج را در فایلی به نام report.xml با فرمت JUnit ذخیره می‌کند. این فرمت توسط GitLab برای نمایش خلاصه تست‌ها در رابط کاربری پشتیبانی می‌شود.
  • artifacts: برای ذخیره فایل‌های تولید شده توسط کار.
    • when: always: این اطمینان را می‌دهد که گزارش تست حتی در صورت شکست تست‌ها نیز جمع‌آوری و ذخیره شود.
    • reports: junit: report.xml: این بخش به GitLab می‌گوید که فایل report.xml حاوی نتایج تست در فرمت JUnit است. GitLab از این اطلاعات برای نمایش یکپارچه نتایج تست در صفحه Merge Request و Pipeline استفاده می‌کند.
    • paths: لیست فایل‌ها یا دایرکتوری‌هایی که باید به عنوان مصنوعات ذخیره شوند.

مثال برای پروژه Node.js با Jest:

stages:
  - test

node_tests:
  stage: test
  image: node:18 # استفاده از ایمیج داکر با Node.js نسخه ۱۸
  before_script:
    - npm install # یا yarn install
  script:
    - npm test -- --reporters=default --reporters=jest-junit # اجرای تست‌ها و تولید گزارش JUnit
  artifacts:
    when: always
    reports:
      junit: junit.xml # مسیر پیش‌فرض خروجی jest-junit
    paths:
      - junit.xml
      # - coverage/ # برای گزارش پوشش کد

در این مثال، فرض شده که jest-junit به عنوان یک devDependency نصب شده و در package.json پیکربندی شده تا خروجی را در junit.xml بنویسد.

گام ۵: Commit و Push کردن تغییرات

فایل .gitlab-ci.yml را به مخزن Git خود اضافه، commit و push کنید:

git add .gitlab-ci.yml
git commit -m "Add GitLab CI configuration for automated testing"
git push

پس از push کردن تغییرات، GitLab به طور خودکار یک پایپ‌لاین جدید را بر اساس پیکربندی شما در .gitlab-ci.yml اجرا خواهد کرد.

گام ۶: مشاهده نتایج پایپ‌لاین و تست‌ها

به پروژه خود در GitLab بروید و از منوی سمت چپ، گزینه CI/CD > Pipelines را انتخاب کنید. در اینجا می‌توانید وضعیت پایپ‌لاین در حال اجرا یا آخرین پایپ‌لاین اجرا شده را مشاهده کنید.

با کلیک بر روی پایپ‌لاین، می‌توانید جزئیات مراحل و کارهای انجام شده را ببینید. اگر روی کار مربوط به تست کلیک کنید، خروجی کنسول (log) آن کار نمایش داده می‌شود.

همچنین، به لطف بخش artifacts:reports:junit، نتایج تست‌ها به صورت یکپارچه در GitLab نمایش داده می‌شوند. در صفحه Merge Request و همچنین در تب Tests مربوط به پایپ‌لاین، می‌توانید خلاصه‌ای از تست‌های موفق، ناموفق و نادیده گرفته شده را مشاهده کنید.

بهترین شیوه‌ها برای ادغام تست‌های خودکار در GitLab CI

برای بهره‌وری بیشتر و نگهداری آسان‌تر، به نکات زیر توجه کنید:

  • اجرای موازی تست‌ها: اگر مجموعه تست‌های شما بزرگ است، آن‌ها را به چند کار موازی تقسیم کنید تا زمان اجرای کلی پایپ‌لاین کاهش یابد. GitLab CI این امکان را با استفاده از کلمه کلیدی parallel فراهم می‌کند.
  • بهینه‌سازی زمان اجرای تست: تست‌های کند می‌توانند سرعت بازخورد را کاهش دهند. تست‌های خود را بهینه کنید و تست‌های طولانی‌تر (مانند E2E) را در مراحل جداگانه یا با فرکانس کمتری اجرا کنید.
  • استفاده از Runnerهای مناسب: برای کارهای سنگین یا نیازمند منابع خاص، از Specific Runnerها با مشخصات مناسب استفاده کنید.
  • مدیریت داده‌های حساس: از متغیرهای CI/CD در GitLab برای ذخیره اطلاعات حساس مانند توکن‌ها یا کلیدهای API استفاده کنید و آن‌ها را مستقیماً در فایل .gitlab-ci.yml قرار ندهید.
  • پوشش کد (Code Coverage): گزارش‌های پوشش کد را تولید و به عنوان مصنوع ذخیره کنید. GitLab می‌تواند این گزارش‌ها را تجزیه و تحلیل کرده و در رابط کاربری نمایش دهد. برای این کار، باید از ابزارهای پوشش کد مربوط به زبان برنامه‌نویسی خود استفاده کنید و خروجی آن را در .gitlab-ci.yml با استفاده از coverage keyword پیکربندی نمایید. # ... بخش‌های دیگر کار تست ... coverage: '/\d+\%\s*coverage/' # یک عبارت منظم برای استخراج درصد پوشش از خروجی کنسول artifacts: paths: - htmlcov/ # اگر گزارش HTML تولید می‌کنید - coverage.xml # اگر گزارش XML تولید می‌کنید reports: cobertura: coverage.xml # برای نمایش پوشش کد در GitLab UI
  • کوچک و متمرکز نگه داشتن کارها: هر کار باید یک مسئولیت مشخص داشته باشد. این کار اشکال‌زدایی و نگهداری را ساده‌تر می‌کند.
  • استفاده از Cache: برای سرعت بخشیدن به پایپ‌لاین‌ها، وابستگی‌ها (مانند پکیج‌های node_modules یا pip) را کش کنید تا در اجراهای بعدی نیازی به دانلود مجدد آن‌ها نباشد. # ... بخش‌های دیگر کار تست ... cache: key: ${CI_COMMIT_REF_SLUG} # کلید کش می‌تواند بر اساس شاخه باشد paths: - .pip-cache/ # برای پایتون با pip - node_modules/ # برای Node.js

مفاهیم پیشرفته‌تر (به طور خلاصه)

  • اجرای شرطی کارها (Conditional Job Execution): با استفاده از rules یا only/except می‌توانید تعیین کنید که یک کار تحت چه شرایطی (مثلاً فقط برای شاخه‌های خاص یا تگ‌ها) اجرا شود.
  • محیط‌های تست (Test Environments): برای تست‌های یکپارچه‌سازی یا E2E، ممکن است نیاز به راه‌اندازی سرویس‌های جانبی (مانند پایگاه داده) داشته باشید. می‌توانید از services در .gitlab-ci.yml برای این منظور استفاده کنید.
  • Triggering Pipelines: پایپ‌لاین‌ها می‌توانند توسط رویدادهای مختلفی (push، merge request، تگ، زمان‌بندی شده، API) فعال شوند.

نتیجه‌گیری

ادغام تست‌های خودکار در GitLab CI یک سرمایه‌گذاری هوشمندانه برای هر تیم توسعه نرم‌افزار است. این فرآیند نه تنها به شناسایی زودهنگام خطاها و بهبود کیفیت محصول کمک می‌کند، بلکه با خودکارسازی وظایف تکراری، سرعت توسعه را نیز افزایش می‌دهد. با استفاده از راهنمایی‌ها و مثال‌های ارائه شده در این مقاله، شما می‌توانید به سادگی تست‌های خودکار پروژه خود را در پایپ‌لاین CI/CD GitLab ادغام کرده و از مزایای بی‌شمار آن بهره‌مند شوید. به یاد داشته باشید که پیکربندی اولیه تنها قدم اول است؛ بهینه‌سازی مداوم پایپ‌لاین‌ها و مجموعه تست‌ها برای دستیابی به بهترین نتایج ضروری خواهد بود.


سوالات متداول

آیا می‌توانم از Docker image سفارشی برای اجرای تست‌هایم در GitLab CI استفاده کنم؟ 

بله، شما می‌توانید از هر Docker image موجود در Docker Hub یا رجیستری‌های خصوصی خودتان استفاده کنید. کافی است نام ایمیج را در بخش image کار مربوطه در فایل .gitlab-ci.yml مشخص کنید. اگر ایمیج شما در یک رجیستری خصوصی است، باید اطلاعات احراز هویت را نیز پیکربندی نمایید.

چگونه می‌توانم نتایج تست‌های ناموفق را به سرعت بررسی کنم؟

 GitLab نتایج تست‌ها را (در صورت استفاده از فرمت گزارش JUnit) به صورت یکپارچه در صفحه Merge Request و در بخش Tests پایپ‌لاین نمایش می‌دهد. شما می‌توانید لیست تست‌های ناموفق را به همراه پیام خطای آن‌ها مشاهده کنید. همچنین، با کلیک بر روی کار ناموفق، به لاگ کامل آن دسترسی خواهید داشت که جزئیات بیشتری را ارائه می‌دهد.

آیا امکان اجرای تست‌ها فقط بر روی تغییرات جدید کد وجود دارد؟

 اجرای تست‌ها فقط بر روی بخش‌های تغییر یافته کد (Incremental Testing) می‌تواند پیچیده باشد و به ابزارها و استراتژی‌های خاصی نیاز دارد. GitLab CI به طور پیش‌فرض تمام تست‌های تعریف شده در اسکریپت را اجرا می‌کند. با این حال، شما می‌توانید با اسکریپت‌نویسی سفارشی و استفاده از ابزارهایی که تغییرات فایل را تشخیص می‌دهند، این قابلیت را تا حدی پیاده‌سازی کنید. اغلب، اجرای کامل مجموعه تست‌های واحد (که سریع هستند) بر روی هر تغییر، رویکرد مطمئن‌تری است.

تفاوت بین stages و jobs در GitLab CI چیست؟

 Stages (مراحل) ترتیب کلی اجرای پایپ‌لاین را تعریف می‌کنند (مثلاً ابتدا build، سپس test، و در نهایت deploy). تمامی Jobs (کارها) متعلق به یک مرحله، پس از موفقیت کامل مرحله قبلی، شروع به اجرا می‌کنند (و اگر منابع اجازه دهد، به صورت موازی). یک Job واحدی از اجراست که یک اسکریپت خاص را روی یک Runner اجرا می‌کند.

چگونه می‌توانم گزارش پوشش کد (Code Coverage) را در GitLab CI مشاهده کنم؟ 

ابتدا باید ابزار پوشش کد مناسب برای زبان و فریمورک خود را پیکربندی کنید تا گزارش پوشش کد را تولید نماید (معمولاً به فرمت XML مانند Cobertura یا به صورت متنی). سپس، در فایل .gitlab-ci.yml، باید با استفاده از کلمه کلیدی coverage یک عبارت منظم (regex) برای استخراج درصد پوشش از خروجی کنسول کار تست خود تعریف کنید. همچنین، می‌توانید فایل گزارش کامل (مثلاً XML یا HTML) را به عنوان artifact ذخیره کرده و با artifacts:reports:cobertura آن را برای نمایش در GitLab UI مشخص کنید.

بیشتر بخوانید:

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