فرم گزارش معمولاً به دو بخش تقسیم میشود. بخش اول گزینههای سفارشی گزارش را پیکربندی میکند و ظاهر آن برای هر report plugin متفاوت است. بخش دوم گزینههای سیستمی (دسترسی، اعلانها و زمانبندی) را تعریف میکند و برای همه report pluginها یکسان است. در این بخش توضیح میدهیم چطور فرم گزارش را مقداردهی کنید و چطور با استفاده از این گزینهها، گزارشهای تولیدشده را سفارشیسازی کنید.
گزینههای فرم #
همه report pluginهای داخلی TestRail تا حد زیادی قابل سفارشیسازی هستند و معمولاً میتوانید scope، چیدمان و سطح جزئیاتی را که در گزارشهای تولیدشده میآید تنظیم کنید. برای ساختاردهی و گروهبندی گزینههای مختلف، استفاده از tab control ایده خوبی است و معمولاً اولین قدم در طراحی یک فرم گزارش جدید هم همین است:
<div class="tabs">
<div class="tab-header">
<a href="javascript:void(0)" class="tab1 current" rel="1"
onclick="App.Tabs.activate(this)">
<?= lang('reports_tpr_form_details') ?></a>
<a href="javascript:void(0)" class="tab2" rel="2"
onclick="App.Tabs.activate(this)">
<?= lang('reports_tpr_form_runs') ?></a>
</div>
<div class="tab-body tab-frame">
<div class="tab tab1">
<!-- The content of tab 1 goes here -->
</div>
<div class="tab tab2 hidden">
<!-- The content of tab 2 goes here -->
</div>
</div>
</div>
برای report pluginهایی که بیش از یک هدف را پوشش میدهند، معمولاً بهتر است سطح جزئیات قابل تنظیم باشد. همانطور که به خاطر دارید، report plugin ما باید گزارشهایی را render کند که توزیع نتایج را برای نوعهای test case و اولویتها نشان میدهند. در این حالت، گزینههای مفید میتوانند شامل کردن یا حذف کردن هرکدام از این موارد باشند.
برای این کار، به report.php برمیگردیم و functionهای مربوط به فرم را تکمیل میکنیم. با prepare_form شروع میکنیم؛ این function فرم را آماده میکند و گزینههای ما را ثبت میکند:
public function prepare_form($context, $validation)
{
// Assign the validation rules for the fields on the form.
$validation->add_rules(
array(
'custom_types_include' => array(
'type' => 'bool',
'default' => false
),
'custom_priorities_include' => array(
'type' => 'bool',
'default' => false
)
)
);
if (request::is_post())
{
return;
}
// We assign the default values for the form depending on the
// event. For 'add', we use the default values of this plugin.
// For 'edit/rerun', we use the previously saved values of
// the report/report job to initialize the form. Please note
// that we prefix all fields in the form with 'custom_' and
// that the storage format omits this prefix (validate_form).
if ($context['event'] == 'add')
{
$defaults = array(
'types_include' => true,
'priorities_include' => true
);
}
else
{
$defaults = $context['custom_options'];
}
foreach ($defaults as $field => $value)
{
$validation->set_default('custom_' . $field, $value);
}
}
این function دو کار انجام میدهد. قدم اول این است که قوانین اعتبارسنجی گزینهها را با استفاده از $validation object ارسالشده تنظیم کنیم؛ قدم دوم هم تنظیم مقدارهای پیشفرض برای این گزینههاست. توجه کنید که چطور از $context parameter استفاده میکنیم تا مشخص کنیم گزارش جدیدی اضافه میشود یا یک گزارش موجود ویرایش/دوباره اجرا میشود، و مدیریت مقدارهای پیشفرض در این دو حالت چه تفاوتی دارد.
بعد میتوانیم validate_form را تکمیل کنیم تا گزینهها validate و برگردانده شوند:
public function validate_form($context, $input, $validation)
{
// At least one detail entity option must be selected (types or
// priorities).
if (!$input['custom_types_include'] &&
!$input['custom_priorities_include'])
{
$validation->add_error(
lang('reports_tpr_form_details_include_required')
);
return false;
}
$values = array();
static $fields = array(
'types_include',
'priorities_include'
);
foreach ($fields as $field)
{
$key = 'custom_' . $field;
$values[$field] = arr::get($input, $key);
}
return $values;
}
سناریوهای ساده اعتبارسنجی از قبل با قوانین اعتبارسنجیای که در prepare_form تعریف کردهایم پوشش داده میشوند، و validate_form میتواند برای سناریوهای پیچیدهتر استفاده شود. برای مثال، اینجا از آن استفاده میکنیم تا مطمئن شویم حداقل یک مورد در فرم انتخاب شده است (types یا priorities). سپس فقط گزینههای گزارش را همانطور که باید برای مرحله rendering ذخیره شوند برمیگردانیم.
بعد دوباره به form.php برمیگردیم و میتوانیم کد مربوط را به فرم اضافه کنیم:
..
<!-- The content of tab 1 goes here -->
<p class="top"><?= lang('reports_tpr_form_details_include') ?></p>
<div class="checkbox form-checkbox" style="margin-left: 15px">
<label>
<?= lang('reports_tpr_form_details_include_types') ?>
<input type="checkbox" id="custom_types_include"
name="custom_types_include" value="1"
<?= validation::get_checked('custom_types_include',1) ?> />
</label>
</div>
<div class="checkbox" style="margin-left: 15px">
<label>
<?= lang('reports_tpr_form_details_include_priorities') ?>
<input type="checkbox" id="custom_priorities_include"
name="custom_priorities_include" value="1"
<?= validation::get_checked('custom_priorities_include',1) ?> />
</label>
</div>
..

کنترلهای فرم #
با اینکه حتی فرمهای پیچیده را هم میتوان با روش گزینههای سفارشی ساخت، بسیاری از report pluginها گزینههای مشترکی دارند و منطقی نیست این گزینهها را بارها پیادهسازی کنیم. خوشبختانه reporting engine در TestRail قابلیتی به نام form controls دارد که گزینههای رایج را پیادهسازی میکند و هم در report pluginهای داخلی و هم در report pluginهای سفارشی قابل استفاده مجدد است. برای انتخاب مجموعهای از statusها، کاربران، test suiteها، test runها و موارد دیگر، کنترلهای آماده وجود دارد.
این بخش توضیح میدهد چطور از form controls برای پیکربندی scope مربوط به report plugin استفاده کنید. در این مثال، منظور ما از scope همان test runهایی است که در گزارشهای تولیدشده قرار میگیرند، و برای این کار از form controlهای انتخاب run و محدود کردن run استفاده میکنیم. کافی است به report.php برگردیم و کد زیر را اضافه یا اصلاح کنیم:
class Tests_property_results_report_plugin extends Report_plugin
{
private $_controls;
// The controls and options for those controls that are used on
// the form of this report.
private static $_control_schema = array(
'runs_select' => array(
'namespace' => 'custom_runs',
'multiple_suites' => true
),
'runs_limit' => array(
'type' => 'limits_select',
'namespace' => 'custom_runs',
'min' => 0,
'max' => 100,
'default' => 25
)
);
..
public function __construct()
{
parent::__construct();
$this->_controls = $this->create_controls(
self::$_control_schema
);
}
public function prepare_form($context, $validation)
{
// Assign the validation rules for the controls used on the
// form.
$this->prepare_controls($this->_controls, $context,
$validation);
..
}
public function validate_form($context, $input, $validation)
{
..
// We begin with validating the controls used on the form.
$values = $this->validate_controls(
$this->_controls,
$context,
$input,
$validation);
if (!$values)
{
return false;
}
..
}
public function render_form($context)
{
$params = array(
'controls' => $this->_controls,
'project' => $context['project']
);
..
}
}
در واقع، کنترلها را در constructor و بر اساس schema تعریفشده میسازیم، آنها را در prepare_form ثبت میکنیم و در validate_form اعتبارسنجی میکنیم. همچنین مطمئن میشویم کنترلها به view فرم ارسال میشوند. حالا فقط باید کد front-end مربوط را در form.php:
//The content of tab 2 goes here
$report_obj->render_control(
$controls,
'runs_select',
array(
'top' => true,
'project' => $project
)
)
$report_obj->render_control(
$controls,
'runs_limit',
array(
'intro' => lang('report_plugins_runs_limit'),
'limits' => array(5, 10, 25, 50, 100, 0)
)
)
حالا وقتی در فرم گزارش به تب Test Suites & و Runs بروید، باید چیزی شبیه نمونه زیر ببینید:

توجه داشته باشید که با اضافه کردن پشتیبانی از کنترلها به methodهای فرم در report.php ، مقدارهای انتخابشده کنترلها اکنون بهصورت خودکار در گزینههای گزارش ذخیره میشوند و از طریق پارامتر استاندارد $options هنگام render کردن گزارش در دسترس قرار میگیرند. این موضوع در بخش بعدی نشان داده میشود.
Report helper #
مشابه form controls، reporting engine در TestRail برای خواندن دادههای واقعی از database، به queryهای رایج مرتبط با database هم دسترسی میدهد. این queryها از طریق methodهای object در چیزی به نام report helper در دسترس هستند. این helper از طریق $this→_helper در report.php و $report_helper در viewهای گزارش.
بسیاری از functionهای این helper برای استفاده همراه با کنترلهای فرم طراحی شدهاند؛ این موضوع در مثال بعدی روشنتر میشود. حالا به rendering واقعی گزارش میرویم (run method) و scope گزارش را تنظیم میکنیم:
public function run($context, $options)
{
$project = $context['project'];
// Read the test suites first.
$suites = $this->_helper->get_suites_by_include(
$project->id,
$options['runs_suites_ids'],
$options['runs_suites_include']
);
$suite_ids = obj::get_ids($suites);
// We then get the actual list of test runs used, depending on
// the report options.
if ($suite_ids)
{
$runs = $this->_helper->get_runs_by_include(
$project->id,
$suite_ids,
$options['runs_include'],
$options['runs_ids'],
$options['runs_filters'],
null, // Active and completed
$options['runs_limit'],
$run_rels,
$run_count
);
}
else
{
$runs = array();
$run_rels = array();
$run_count = 0;
}
$run_ids = obj::get_ids($runs);
..
}
این کار از گزینههای کنترلهای فرم (بخشی از $options parameter) استفاده میکند تا test suiteها و test runهای مرتبط با گزارش را از database بخواند. report helper methodهای بیشتری هم دارد؛ برای دیدن نمای کاملتر، بهتر است source code پلاگینهای گزارش داخلی را در app/plugins/reports بررسی کنید.
مراحل بعدی #
در بخش آخر ادامه دهید تا یاد بگیرید چطور برای queryهای سفارشی مستقیماً به database دسترسی داشته باشید و دادههای خود را render کنید:

