TestRail چند defect plugin آماده برای bug trackerهای رایج مثل Jira، FogBugz، Bugzilla و ابزارهای دیگر دارد. اگر bug tracker خود را سفارشی کردهاید (مثلاً custom field اضافه کردهاید) یا میخواهید قابلیتهای بیشتری به یک defect plugin اضافه کنید، میتوانید defect pluginهای داخلی را مطابق نیازتان سفارشی کنید. TestRail کد منبع کامل defect pluginهای پیشفرض را در اختیار شما میگذارد و این مقاله چند نمونه از سفارشیسازی آنها را نشان میدهد.
اگر قصد دارید یکی از defect pluginهای ارائهشده را سفارشی کنید، توصیه میکنیم ابتدا مقاله ساخت defect plugin سفارشی را بخوانید، چون اطلاعات پسزمینهای مهمی درباره سازوکار داخلی defect pluginها ارائه میدهد. در ادامه، نمونههایی از اضافه کردن فیلدهای بیشتر به Push Defect dialog و پیادهسازی user mapping را میبینید.
افزودن custom fieldها #
افزودن یک فیلد جدید به Push Defect dialog زمانی مفید است که از custom fieldهای اضافی و الزامی استفاده میکنید که defect pluginهای پیشفرض از آنها پشتیبانی نمیکنند. همچنین ممکن است بخواهید فیلدهای دیگری، مثل Assigned To را به dialog اضافه کنید؛ در این بخش نحوه انجام آن را توضیح میدهیم. در این مثال از defect plugin مربوط به Jira استفاده میکنیم، اما defect pluginهای دیگر هم مشابه همین کار میکنند. قبل از سفارشیسازی defect plugin مربوط به Jira، ابتدا آن را کپی میکنیم و نامش را تغییر میدهیم. قرار است Jira.php فایل plugin را از دایرکتوری برنامه TestRail به دایرکتوری custom کپی کنیم:
Original: <TestRail>/app/plugins/defects/Jira.php
Copy To: <TestRail>/custom/defects/Jira_custom.php
دقت کنید که نام فایل را به Jira_custom.php. تغییر دادهایم. این کار مهم است، چون به شما امکان میدهد در بخش Administration در TestRail همچنان بین plugin استاندارد Jira و نسخه سفارشیشده خودتان یکی را انتخاب کنید. پس از کپی کردن فایل، باید نام class را تغییر دهیم. برای این کار، کافی است Jira_custom.php فایل را در یک text editor باز کنید و نام class را در ابتدای فایل به شکل زیر تغییر دهید:
class Jira_custom_defect_plugin extends Defect_plugin
{
}
در این مثال، میخواهیم یک فیلد جدید به Push Defect dialog اضافه کنیم؛ این فیلد به testerها اجازه میدهد configuration سختافزاری و نرمافزاری سیستم تستی را که issue یا bug روی آن رخ داده است مشخص کنند. فیلد متناظر در Jira یک custom field از نوع Text Field است و نام آن Config است. این فیلد برای همه issue typeها معتبر است و الزامی نیست.
اولین چیزی که باید تغییر دهیم، form schema در prepare_push method است (اگر هنوز مقاله ساخت defect plugin سفارشی را نخواندهاید، حتماً آن را بخوانید). کافی است یک string field جدید به dialog اضافه کنیم تا کاربران بتوانند configuration سیستم را برای bug report وارد کنند. نام فیلد را config میگذاریم و آن را درست قبل از description field اضافه میکنیم:
public function prepare_push($context)
{
// Return a form with the following fields/properties
return array(
'fields' => array(
'summary' => array(
'type' => 'string',
'label' => 'Summary',
'required' => true,
'size' => 'full'
),
'type' => array(
'type' => 'dropdown',
'label' => 'Issue Type',
'required' => true,
'remember' => true,
'size' => 'compact'
),
'project' => array(
'type' => 'dropdown',
'label' => 'Project',
'required' => true,
'remember' => true,
'cascading' => true,
'size' => 'compact'
),
'component' => array(
'type' => 'dropdown',
'label' => 'Component',
'required' => true,
'remember' => true,
'depends_on' => 'project',
'size' => 'compact'
),
'config' => array(
'type' => 'string',
'label' => 'Configuration',
'remember' => true,
'size' => 'full'
),
'description' => array(
'type' => 'text',
'label' => 'Description'
)
)
);
}
پس از اینکه فیلد را به form schema اضافه کردیم، فیلد config را به prepare_field method اضافه میکنیم. این کار را انجام میدهیم تا configuration ذخیرهشدهای را که کاربر قبلاً در dialog وارد کرده است بازیابی کنیم. به این ترتیب، کاربر لازم نیست برای هر bug report که ارسال میشود دوباره configuration را وارد کند. توجه کنید که کد مربوط به مدیریت preference را به ابتدای method منتقل میکنیم تا بتوانیم از آن برای فیلد جدید config استفاده کنیم:
public function prepare_field($context, $input, $field)
{
$data = array();
// Take into account the preferences of the user, but only
// for the initial form rendering (not for dynamic loads).
if ($context['event'] == 'prepare')
{
$prefs = arr::get($context, 'preferences');
}
else
{
$prefs = null;
}
// Process those fields that do not need a connection to the
// Jira installation.
if ($field == 'summary' || $field == 'description' || $field == 'config')
{
switch ($field)
{
case 'summary':
$data['default'] = $this->_get_summary_default(
$context);
break;
case 'description':
$data['default'] = $this->_get_description_default(
$context);
break;
case 'config':
$data['default'] = arr::get($prefs, 'config');
break;
}
return $data;
}
// [ .. ]
}
اکنون که اسکریپت تنظیمات configuration قبلی را بازیابی میکند، آخرین گام این است که custom field جدید را به درخواست API اضافه کنیم که برای ایجاد issue به Jira میفرستیم. برای این کار، push method را به شکل زیر تغییر میدهیم:
public function push($context, $input)
{
$api = $this->_get_api();
$data = array();
$data['summary'] = $input['summary'];
$data['type'] = $input['type'];
$data['project'] = $input['project'];
$data['component'] = $input['component'];
$data['description'] = $input['description'];
$data['customFieldValues'] = array(
array(
'customfieldId' => 'customfield_10000',
'values' => array($input['config'])
)
);
return $api->add_issue($data);
}
باید نام customfield_10000 را تنظیم کنید و از ID واقعی custom fieldهایی که میخواهید ارسال شوند استفاده کنید. حالا که فیلد جدید را به custom defect plugin خود اضافه کردهایم، Push Defect dialog بهروزرسانیشده میتواند جزئیات configuration را همراه issue ارسال کند (حتماً plugin جدید Jira_custom plugin را از مسیر Administration > Site Settings انتخاب کنید تا فیلد جدید را ببینید).

میتوانید فایل نمونه کامل را از لینک زیر دانلود کنید.
نمونه defect plugin سفارشی Jira #
فایل نمونه PHP شامل کد اسکریپت defect plugin سفارشی Jira
افزودن فیلدهای داخلی #
افزودن فیلدهای داخلیِ بیشتر از bug tracker به فرم Push Defect تفاوت زیادی با افزودن فیلدهای سفارشی bug tracker که در بالا توضیح دادیم ندارد. با این حال، چون این کار بسیار رایج است و API بعضی bug trackerها برای فیلدهای خاص به قراردادهای ویژهای نیاز دارد، در این بخش توضیح میدهیم چطور یک فیلد داخلیِ دیگر از bug tracker را به defect plugin اضافه کنید.
در این بخش بهطور مشخص توضیح میدهیم چطور فیلد Affects Version در Jira را اضافه کنید؛ البته bug trackerهای دیگر هم فیلدها و قراردادهای مشابهی دارند. فیلد Affects Version بهصورت یک dropdown پیادهسازی میشود تا نسخهای را انتخاب کنید که باگ جدید باید برای آن گزارش شود. ابتدا defect plugin استاندارد Jira را در دایرکتوری سفارشی خود کپی میکنیم و نام آن را تغییر میدهیم:
Original: <TestRail>/app/plugins/defects/Jira.php
Copy To: <TestRail>/custom/defects/Jira_versions.php
همچنین باید دوباره نام class را در ابتدای فایل تنظیم کنیم:
class Jira_versions_defect_plugin extends Defect_plugin
{
}
اولین تغییر واقعی در کد، اضافه کردن فیلد جدید به schema فرم است. نام این فیلد را میگذاریم affects_version:
public function prepare_push($context)
{
// Return a form with the following fields/properties
return array(
'fields' => array(
'summary' => array(
'type' => 'string',
'label' => 'Summary',
'required' => true,
'size' => 'full'
),
'type' => array(
'type' => 'dropdown',
'label' => 'Issue Type',
'required' => true,
'remember' => true,
'size' => 'compact'
),
'project' => array(
'type' => 'dropdown',
'label' => 'Project',
'required' => true,
'remember' => true,
'cascading' => true,
'size' => 'compact'
),
'component' => array(
'type' => 'dropdown',
'label' => 'Component',
'required' => true,
'remember' => true,
'depends_on' => 'project',
'size' => 'compact'
),
'affects_version' => array(
'type' => 'dropdown',
'label' => 'Affects Version',
'required' => false,
'remember' => true,
'depends_on' => 'project',
'size' => 'compact'
),
'description' => array(
'type' => 'text',
'label' => 'Description'
)
)
);
}
برای اینکه بتوانیم نسخههای موجود برای یک project را از Jira دریافت کنیم، یک get_versions method جدید به class Jira_api اضافه میکنیم:
/**
* Get Versions
*
* Returns a list of versions for a Jira project. The versions
* are returned as array of objects, each with its ID and name.
*/
public function get_versions($project_id)
{
$data = array($project_id);
$response = $this->_send_command('getVersions', $data);
if (!$response)
{
return array();
}
$result = array();
foreach ($response as $version)
{
$c = obj::create();
$c->id = (string) $version->id;
$c->name = (string) $version->name;
$result[] = $c;
}
return $result;
}
همچنین باید dropdown خود را با نسخههای موجود در Jira پر کنیم؛ بنابراین prepare_field method را بهروزرسانی میکنیم و کد زیر را به دومین switch statement اضافه میکنیم:
case 'affects_version':
if (isset($input['project']))
{
$data['default'] = arr::get($prefs, 'affects_version');
$data['options'] = $this->_to_id_name_lookup(
$api->get_versions($input['project'])
);
}
break;
در نهایت، باید وقتی کاربر گزارش باگ را ارسال میکند، فیلد نسخه را هم به Jira بفرستیم. چون Jira از چند نسخه برای یک issue پشتیبانی میکند، باید این فیلد را بهصورت array ارسال کنیم. برای این کار، کافی است کد زیر را به add_issue method اضافه کنید:
if (isset($options['affects_version']))
{
$version = array(
'id' => $options['affects_version'],
'archived' => false,
'released' => false
);
$options['affectsVersions'] = array(
$version
);
}
وقتی Jira_version defect plugin جدید را از مسیر Administration > Site Settings > Integration tab انتخاب کنید، Push Defect dialog به این شکل نمایش داده میشود:

میتوانید فایل نمونه کامل را از لینک زیر دانلود کنید.
نمونه نسخههای سفارشی Jira #
فایل نمونه PHP شامل کد اسکریپت نسخههای سفارشی Jira
پیادهسازی user mappings #
#
اکنون راه سادهتری برای map کردن کاربران بین TestRail و ابزار bug tracking شما وجود دارد، بدون اینکه لازم باشد تغییری در کد ایجاد کنید. برای اطلاعات بیشتر، به مقاله متغیرهای کاربر.
defect pluginهایی که همراه TestRail ارائه میشوند، از یک حساب کاربری واحد برای ارسال bug report به سیستم third-party مربوطه استفاده میکنند. این روش در بسیاری از شرایط خوب کار میکند و توصیه میشود برای این کار یک کاربر ویژه با نام testrail یا نامی مشابه در bug tracker اضافه کنید.
اما اگر میخواهید برای کاربری که bug report را ارسال کرده، از حساب کاربری واقعی او در bug tracker استفاده شود، میتوانید این کار را با اضافه کردن user mapping به defect plugin پیادهسازی کنید. برای نمایش این روش، دوباره Jira.php plugin را کپی کرده و نامش را تغییر میدهیم:
Original: <TestRail>/app/plugins/defects/Jira.php
Copy To: <TestRail>/custom/defects/Jira_users.php
همچنین نام class مربوط به defect plugin را بهروزرسانی میکنیم:
class Jira_users_defect_plugin extends Defect_plugin
{
}
برای اضافه کردن قابلیت user mapping به script، یک [users] section جدید به configuration اضافه میکنیم تا administratorها بتوانند بین کاربر TestRail، که با آدرس ایمیل کاربر شناسایی میشود، و اطلاعات ورود ابزار defect tracking یک mapping تعریف کنند. برای مثال، configuration در بخش administration به این شکل خواهد بود:
; Please configure your Jira connection below
[connection]
address=http://jira/
user=testrail
password=secret
[users]
bob@example.com=bob:secret
jim@example.com=jim:secret
jane@example.com=jane:secret
وقتی Bob یک bug report ارسال میکند، defect script بهروزرسانیشده از credentials مربوط به Jira برای Bob استفاده میکند تا bug را ثبت کند. اگر کاربری که credentials او هنوز تنظیم نشده است بخواهد bug report ارسال کند، script به login سراسری تنظیمشده برمیگردد؛ همان موردی که در [connection] section مشخص شده است. حالا get_meta method را بهروزرسانی میکنیم تا optionهای جدید configuration نمایش داده شوند:
private static $_meta = array(
'author' => 'Gurock Software',
'version' => '1.0',
'description' => 'Jira defect plugin for TestRail',
'can_push' => true,
'can_lookup' => true,
'default_config' =>
'; Please configure your Jira connection below
[connection]
address=http:///
user=testrail
password=secret
[users]
user@example.com=user:secret'
);
همچنین configure method را بهروزرسانی میکنیم تا [users] section را به یک field داخلی اختصاص دهد:
public function configure($config)
{
$ini = ini::parse($config);
$this->_address = str::slash($ini['connection']['address']);
$this->_user = $ini['connection']['user'];
$this->_password = $ini['connection']['password'];
if (isset($ini['users']))
{
$this->_users = $ini['users'];
}
else
{
$this->_users = array();
}
}
مورد بعدی که باید تغییر دهیم، authentication واقعی Jira API است. برای این کار باید کد user mapping را به _get_api method اضافه کنیم، به این شکل:
private function _get_api($context = null)
{
if ($this->_api)
{
return $this->_api;
}
$user = $this->_user;
$password = $this->_password;
// Find the appropriate Jira user for the bug reporter
// (by mapping the current TestRail user to her Jira
// account).
if ($context && $this->_users)
{
$credentials = arr::get(
$this->_users,
str::to_lower($context['user']->email)
);
if ($credentials)
{
if (preg_match('/([^:]+):(.+)/', $credentials, $matches))
{
$user = $matches[1];
$password = $matches[2];
}
}
}
$this->_api = new Jira_api($this->_address);
$this->_api->login($user, $password);
return $this->_api;
}
این method سعی میکند credentials متناظر با کاربر فعلی را در configuration پیدا کند. اگر credentials پیدا نشود، از credentials سراسری تنظیمشده بهعنوان fallback استفاده میکند. توجه کنید که $context argument را به _get_api method اضافه کردهایم. این argument لازم است تا بتوانیم آدرس ایمیل کاربر فعلی TestRail را بگیریم.
حالا فقط باید $context variable را از prepare_field و push methodها به این شکل پاس بدهیم. توجه داشته باشید که نباید $context argument را در lookup method اضافه کنید، چون هیچ context informationای ندارد:
$api = $this->_get_api($context);
تمام شد. حالا که user mapping را به _get_api method اضافه کردهایم و context information را هم به این method پاس دادهایم، تنها کاری که باقی میماند این است که defect plugin جدیدمان را از مسیر Administration > Site Settings انتخاب کنیم و حسابهای کاربری را تنظیم کنیم.
جایگزین user mapping #
#
اکنون راه سادهتری وجود دارد که بدون تغییر در کد، کاربران را بین TestRail و ابزار bug tracking خود map کنید. میتوانید اطلاعات بیشتر را در مقاله متغیرهای کاربر.
بعضی از issue trackerها و defect trackerها به شما اجازه میدهند کاربر reporter را از طریق API تنظیم کنید. به این ترتیب لازم نیست حتما یک user mapping کامل بر اساس loginها پیادهسازی کنید؛ میتوانید فقط username کاربری را مشخص کنید که issue را گزارش کرده است.
برای مثال، فرض کنید آدرسهای ایمیل سازمان شما و usernameهای متناظر آنها در Jira به این شکل هستند:
bob@example.com -> bob
jan@example.com -> jan
sue@example.com -> sue
بعد میتوانید بهسادگی username مربوط به Jira را از آدرس ایمیل کاربر فعلی بسازید و reporter field را در push method به این شکل مشخص کنید:
public function push($context, $input)
{
if (isset($context['user']->email))
{
$email = $context['user']->email;
$pos = str::pos($email, '@');
if ($pos !== false)
{
$input['reporter'] = str::sub($email, 0, $pos);
}
}
$api = $this->_get_api();
return $api->add_issue($input);
}
به این شکل، کاربری که issue را گزارش کرده است، بدون اینکه لازم باشد username و password کاربر Jira در TestRail ذخیره شود، بهدرستی به Jira فرستاده میشود. بسته به قابلیتهای API ارائهشده، ابزارهای دیگر برای ردیابی issue و defect هم ممکن است از این روش پشتیبانی کنند.

