ایجاد محیط یکپارچه تست در ری اکت

31 اردیبهشت 1398
درسنامه درس 29 از سری آموزش react (ری اکت)
React-text-continous

در درس قبلی برنامه مان را روی cloud منتشر کردیم، حال در این درس می خواهیم مطمئن شویم که برنامه مان مطابق انتظار کار خواهد کرد.

همچنین قبل از انتشار برنامه، مجموعه ای کامل از تست را روی آن انجام می دهیم تا مطمئن شویم  که برنامه با موفقیت تست ها را پاس می کند.

قصد داریم یک رویه قدم به قدم برای توسعه دهندگان ارائه بدهیم تا با دنبال کردن آن مطمئن شوند که قبل از انتشار برنامه، برنامه را بصورت دستی تست می کنند. اما گاهی اوقات اینکار در هنگام توسعه برنامه اتفاق نمی افتد، خصوصاً هنگامی که تحت فشار شدید ناشی از deadline برنامه قرار داریم. اما بهتر است بدانید که روش های بهتری برای اینکار وجود دارد.

ابتدا تست، بعد انتشار

ایده اصلی کار ما این است که برنامه را تنها پس از اینکه تست ها را با موفقیت گذراند، منتشر کنیم. روش های زیادی برای اینکار وجود دادند. همان طور که در بالا گفتیم، این کار می تواند بصورت دستی انجام شود. اما گاهی اوقات اینکار خیلی خسته کننده شده و ممکن است حتی اینکار را فراموش کنیم... پس راه حل چیست؟

یک راه این است که یک اسکریپت بنویسیم که اگر برنامه همه تست ها را با موفقیت گذراند، آنرا منتشر کند. این ساده ترین روش است، اما نیاز است که یک کپی از اسکریپت را به همه توسعه دهندگان تیم بدهیم.

یک روش دیگر این است که کدهای برنامه مان را روی یک سرور یکپارچگی پیوسته (Continuous Integration) ارسال کنیم تا این سرور تست های مورد نیاز را اجرا کرده و تنها در صورتی که برنامه تست ها را با موفقیت گذراند، آنرا منتشر کند.

مشابه سرویس های هاستینگ، در اینجا هم گزینه های زیادی برای اجرای سرورهای یکپارچگی پیوسته داریم. در زیر لیست تعدادی از سرورهای CI معروف را مشاهده می کنید.

حال نگاهی به روش های مختلفی که برای مدیریت این فرآیند انجام می شود، می اندازیم.

اسکریپت build سفارشی

ما می توانیم یک اسکریپت بنویسیم تا قبل از انتشار یک برنامه، یک سری تست را روی آن اجرا کند. مزایای این روش این است که نیاز به کار با سروهای اضافی ندارید.

حال می خواهیم یک اسکریپت بنویسیم که فرآیند انتشار یک برنامه را برای مان انجام دهد. در این مثال از همان مثال surge.sh درس قبلی استفاده می کنیم. حال یک اسکریپت دیگر به نام deploy.sh در دایرکتوری scripts ایجاد می کنیم:

touch scripts/deploy.sh
chmod u+x scripts/deploy.sh

در اینجا اسکریپت surge را هم اضافه می کنیم (نام آن را به اسم دامین خود تغییر دهید):

#!/usr/local/env bash
surge -p build --domain hateful-impulse.surge.sh

سپس اسکریپت release را در فایل package.json مطابق زیر تعریف کنید:

{
  // ...
  "scripts": {
    "start": "node ./scripts/start.js",
    "build": "node ./scripts/build.js",
    "release": "node ./scripts/release.js",
    "test": "jest"
  },
}

حال فایل scripts/release را ایجاد کنید. در دایرکتوری  روت پروژه، دستور زیر را در ترمینال اجرا کنید:

touch scripts/release.js

داخل این فایل چند اسکریپت خط فرمان را اجرا می کنیم، ابتدا مرحله build را انجام داده، سپس تست ها را اجرا کرده و در نهایت اسکریپت deploy را اجرا می کنیم.

در یک فایل node، مقدار NODE_ENV را برابر test می گذاریم تا در ابزارهای build پروژه از آن استفاده کنیم. همچنین یک اسکریپت را به فایل Node برای اجرای یک دستور از خط فرمان اضافه می کنیم و تمام خروجی ها را در یک آرایه می ریزیم:

process.env.NODE_ENV = 'test';

var chalk = require('chalk');
const exec = require('child_process').exec;

var output = [];
function runCmd(cmd) {
  return new Promise((resolve, reject) => {
    const testProcess = exec(cmd, {stdio:[0,1,2]});

    testProcess.stdout.on('data', msg => output.push(msg));
    testProcess.stderr.on('data', msg => output.push(msg));
    testProcess.on('close', (code) => (code === 0) ? resolve() : reject())
  });
}

هنگام موفقیت آمیز بودن اجرای دستور، تابع ()runCmd  یک promise به نام resolve را بر می گرداند و در صورت بروز یک خطا هنگام اجرای دستور، rejected را بر می گرداند.

اسکریپت release باید بتواند کارهای زیر را انجام دهد:

  • build
  • test
  • انتشار(deploy)
  • گزارش خطاها

می توانید این فرآیند را مطابق زیر تصور کنید:

build()
  .then(runTests)
  .then(deploy)
  .catch(error)

حال یک سری متدهایی را برای استفاده از تابع ()runCmd که در بالا آن را تعریف کردیم، می نویسیم:

function build() {
  console.log(chalk.cyan('Building app'));
  return runCmd("npm run build");
}

function runTests() {
  console.log(chalk.cyan('Running tests...'));
  return runCmd("npm test");
}

function deploy() {
  console.log(chalk.green('Deploying...'));
  return runCmd(`sh -c "${__dirname}/deploy.sh"`);
}

function error() {
  console.log(chalk.red('There was an error'));
  output.forEach(msg => process.stdout.write(msg));
}

بعد از اینکه فایل scripts/release.js تکمیل شد، با اجرای دستور npm run release از انتشار برنامه اطمینان حاصل می کنیم:

npm run release

بعد از پاس شدن همه تست ها، نسخه بروز شده برنامه مان با موفقیت منتشر (Deploy) می شود:

انتشار یک برنامه
انتشار یک برنامه

اما اگر خطایی اتفاق بیفتد می توانیم خروجی دستوراتمان را مشاهده می کنیم، که این شامل متن خطاها هم می شود. حال می خواهیم یک اسکریپت تست را طوری بازنویسی کنیم تا یک خطای عمدی اتفاق بیفتد. برای اینکار فایل src/components/Nav/__test__/Navbar-test.js را مطابق زیر تغییر دهید تا اولین تست با یک خطا مواجه شود:

// ...
it('wraps content in a div with .navbar class', () => {
  wrapper = shallow(<Navbar />);
  expect(wrapper.find('.navbars').length).toEqual(1);
});

با اجرای اسکریپت release با یک خطا مواجه می شویم و در این حالت اسکریپت deploy اجرا نمی شود:

npm run release
تست و اجرای یک برنامه ری اکت
تست و اجرای یک برنامه ری اکت

همان طور که می بینید، می توانید خروجی این تست ناموفق را در Log بیبنید که در این حالت بعد از رفع کردن خطا، باید مجدداً دستور npm run release را اجرا کنیم.

Travis CI

Travis CI یک محیط میزبانی یکپارچگی پیوسته است که به راحتی قابل نصب است.

چون کانتینر را روی گیت هاب ارسال کرده ایم، Travis را روی اکانت گیت هاب مان تنظیم می کنیم.

به سایت travis-ci.org رفته و در سایت ثبت نام کنید:

سایت Travis-ci
سایت Travis-ci

بعد از ثبت نام، روی دکمه + کلیک کرده و ریپازیتوری تان را پیدا کنید:

افزودن یک پروژه به travis-ci
افزودن یک پروژه به travis-ci

در صفحه project روی دکمه active repo کلیک کنید:

افزودن یک ریپازیتوری به travis-ci
افزودن یک ریپازیتوری به travis-ci

حال باید travis را پیکربندی کنیم تا کارهای مورد نظرمان را انجام دهد، که این کارها در واقع اجرای اسکریپت های تست و انتشار برنامه است. برای پیکربندی travis باید یک فایلی به نام .travis.yml در روت پروژه ایجاد کنیم.

touch .travis.yml

حال مطابق زیر در قسمت language ،Node_js و در خط بعدی، شماره نسخه nodejs مان را می نویسیم.

language: node_js
node_js:
  - "5.4"

در مرحله آخر باید فایل travis.yml را به git اضافه کنیم و سپس تغییرات ریپازیتوری را به گیت هاب push کنیم.

git add .travis.yml
git commit -am "Added travis-ci configuration file"
git push github master

حال travis مشابه همان دستور npm test ، برنامه را تست می کند.

اجرای تست یک برنامه ریکت توسط Travis

حال می خواهیم برنامه مان توسط travis منتشر شود. چون قبلاً یک اسکریپت scripts/deploy.sh را برای انتشار برنامه مان نوشته بودیم، از همین اسکریپت برای انتشار استفاده می کنیم.

برای اینکه به travis بگوییم بعد از انتشار برنامه اسکریپت deploy.sh را اجرا کند، باید کلید deploy را به فایل travis.yml اضافه کنیم. حال برای اجرای اسکریپت deploy، فایل پیکربندی yml را مطابق زیر ویرایش کنید:

language: node_js
node_js:
  - "5.4"
deploy:
  provider: script
  script: scripts/deploy.sh
  on:
    branch: master

دفعه بعد که push را انجام دادیم، travis اجرا شده و برنامه به surge ارسال می شود( و یا هر سروری که در اسکریپت scripts/deploy.sh مشخص شده باشد)

برای انتشار روی Github Pages باید یک توکن را به اسکریپت مان اضافه کنیم.

در آدرس https://gist.github.com/domenic/ec8b0fc8ab45f39403dd اطلاعات مفیدی درباره نحوه انتشار برنامه روی Github Pages آمده است.

روش های دیگر

روش های زیاد دیگری وجود دارند که ما بتوانیم قبل از انتشار برنامه، از آن تست بگیریم. سرویس Travis CI یک پروژه خوب متن باز است، اما اگر بخواهیم از آن در پروژه شخصی (private)مان استفاده کنیم باید یک اکانت پولی ایجاد کنیم.

یک سرویس CI متن باز دیگر، Jenkins است که برای کار نیاز به تنظیمات بیشتری دارد(هر چند که کار با آن خیلی راحت است).

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

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش react (ری اکت) توصیه می‌کند:
نویسنده شوید

دیدگاه‌های شما

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