خوب این ههم ادمه همین آموزش ترجمه شده کتابی که گفته بودم
تست بيشتر
قبل از اينكه قابليتهاي بيشتري رو به برنامه TrackStar خودمون اضافه كنيم،ما احتياج داريم كه دوباره تست خودمون رو پيكر بندي كنيم همونطور كه قبلا گفته شده، يونيت تست هاي اضافه شده جديد ما معمولاً اضافه ميشوند به برناممون در محيط توسعه. بنابر اين، حتي بعد از اينكه ما تستمون رو كامل انجام بديم بوسيله مثلاً Delete بازم سطر جديد اضافه خواهد شد.پايگاه داده استفاده مجدد خواهد كرد كه همان شناسه براي درج بعدي خواهد بود.پس ما به اجرا كردن تستمون ادامه خواهيم داد،.ما متوجه شكافي در ID سكانس پروژمون شديم.(كه در طي توسعه برناممون مي تونه گيج كننده باشه)
مشكل اين است كه يونيت تست ها برخلاف همان ديتابيسي كه وب فرم استفاده مي كند وقتي در حال ساخت پروژه جديد هستند اجرا مي شود. به عنوان يك نتيجه، اين يك پتانسيل رو براي برخي مسائل بوجود مي آورند.چيزي كه ما بايد انجام دهيم اين است كه تست خودمون رو براي تست جداگانه تنظيم كنيم،براي پایگاه داده های آینه، که فقط براي تست اختصاص داده شده است.چيزي كه ما احتياج داريم اين است كه يك راه مطمئن شدن از اين كه تست هاي ما هميشه اجرا بشند در شيوههاي مشابه، در برابر داده هاي مشابه.مانند قبل يك تغيير ساده در فايل پيكربندي است،كه ما اون رو به زودي ميسازيم. بعدي از طريق استفاده از fixtures. بدست مي آيد.
يك تست fixtures يك سيستم وضعيت و يا چارچوب است كه تست ها در آن حال اجرا هستند.ما مي خوهايم تست هامون رو در زمان هاي مختلفي اجرا كنيم،و هر بار كه اونها اجرا مي شوند قادر به بازگشت نتايج قابل تكرار باشند.يك fixtures از قبل در نظر ميگيره يك نيك نام و محيط ثابت براي اجراي تست هاي ما است.معمولاً fixtures كاري است تا اطمينان حاصل شود كه همه اشاياء كه در اين تست دخيل هستند همواره به يك حالت خاص مقدار دهي اوليه ميشن. يك نمونه از fixturesبارگذاری از یک جدول پایگاه داده با یک مجموعه ثابت و شناخته شده از داده ها است.
Fixtures ها در yii فايلهاي php هستند كه بر مبگردونن يك آرايه معييين از دادهاغي پيكر بندي شده اوليه رو.آنها معمولا ناميده شدن شبيه جدول ديتابيس نشان داده شدهو مكانشون هم در زير protected/tests/fixtures/ است. بنابر اين براي مشخص كردن پروژه داده fixtures ما بيد يك فايل جديد در زير اين دايركتوري بسازيم و اونو tbl_project.php بناميم.جدول قبل از هر تست در فايل اجرا /tests/unit/ProjectTest.php ميشوند. اين فايل fixture مشخص شده است در بالاي فايل تست ProjectTest.php
class ProjectTest extends CDbTestCase
{
public $fixtures=array
(
'projects'=>'Project',
);
}
پيكربندي مديريت fixtures
راه اندازی این نوعاز پایگاه داده fixturesمي تواند زمان بسياري رو صرف بخشي از فرايند تست كنه. يك بار ديگه Yii مياد، براي نجات از اين يكنواختي بوسيله ازائه كلسا CdbFixtureManager . هنگامي كه به عنوان يك مولفه برنامه پيكربندي بشه ، اون قبليت هاي زير رو براي ما ارائه ميده:
· قبل از اجراي همه تست ها ، اون بازنشاني ميكنه همه جدول هاي مربوط رو به داده ثابت شناخته شده
· قبل از اجراي يك تست ، اون مي تونه جداول مشخص شده رو براي به داده ثابت شناخته شده تنظيم مجدد
· در طي اجراء يك تست اون مي تونه فراهم بكنه دسترسي به رديف هايي از داده ها كه بخشي از يك حالت داده هاي ثابت.
براي استفاده از ميديريت fixture ، ما بايد اون رو تنظيم كنيم در فايل پيكربندي برنامه، اين در حالت عداي براي ما انجام شده هستش وقتي ككه ما يك برنامه جديد ميسازيم. اگ شما فايل پيكر بندي براي تست برنامه هاي خاص هست رو باز كنيد كه در مكان protected/config/test. Php شما ميبينيد كه كامپ.ننت زير تعريف شده است.
'fixture'=>array(
'class'=>'system.test.CDbFixtureManager', ),
بنابر اين برنامه شما براي استفاده از مديريت fixture آماده است . حالا ما احتياج دالريم كه يك fixture جديد بسازيم.
ساخت fixture جديد
يك implemented در yii اجرا شده است به وسيله فايل php كه بر مبگردونه آريه اي رو كه نشون ميده داده هايي رو براي يك جدول خاص. نام فيل شبيه نام جدول است. به زور پيش فرض ، اين فايل fixture انتظار مي رود كه در فولدر protected/tests/fixtures. قرار داشته باشد .شما مي توانيد از CDbFixtureManager::basePath استفاده كنيد پيكر بندي برنامه خودتون براي سفارشي كردن اين مكان اگر مي خواهيد. اجازه دهيد به عنوان مثال يك fixture براي جدول tbl_project بسازيم. يك فايل جديد با نام و مسير مقابل بسازيد protected/tests/fixtures/tbl_project.php با محتويات زير:
<?php
return array(
'project1'=>array(
'name' => 'Test Project 1',
'description' => 'This is test project 1',
'create_time' => '',
'create_user_id' => '',
'update_time' => '',
'update_user_id' => '',
),
'project2'=>array(
'name' => 'Test Project 2',
'description' => 'This is test project 2',
'create_time' => '',
'create_user_id' => '',
'update_time' => '',
'update_user_id' => '',
),
'project3'=>array(
'name' => 'Test Project 3',
'description' => 'This is test project 3',
'create_time' => '',
'create_user_id' => '',
'update_time' => '', 'update_user_id' => '',
),
);
همانطور كه مشاهده مي كنيد، fixture ما آرايه اي است كه نشون ميده ورودي هاي جدول ما رو.مقدار اين كليدها هستند خودشان آرايه با يك جفت key=>value براي هر ستون در جدول. ما سه سطر رو اضافه كرديم ، ام شما مي توانيد سطرهاي بيشتري رو به دلخواه وارد كنيد. براي سادگي كار ، ما فقط مقادير پر شده اي داريم كه قبلا پر شدن و نمي تونن مقدار تهي داشته باشند، كه فيلدهاي name و description هستند .اين داده به قدري هستن كه بتونن براي ما استفاده از fixtures. رو نشون بدن.
شما همچنين ممكن است متوجه شده باشيد كه ستون id در داده fixture قبلي مشخص نشده است.همونطور كه ميدونيد ما اين فيلد رو قبلاً از نوع auto-increment گذاشتيم.
پيكر بندي اين fixture براي استفاده
ما هنوز هم احتياج داريم كه به تست يونيتمون بگيم كه از اين fixture استفاده كنه كه ما اين كار رو در ينويت تست هايمون قبلاً اگر يادو.ن باشه انجام داديم .در اين مورد، ما احتياج خواهيم داشت به اضافه كردن fixture در بالاي هون يونيت تستمون يعني بايد fixture رو اعلان كنيم در اين فايل مانند زير:
<?php
class ProjectTest extends CDbTestCase
{
public $fixtures=array
(
'projects'=>'Project',
);
}
بنابر اين ، انچه كه ما انجام داديم مشخص است $fixturesعضو متغیربهیک آرایهاستکهمشخص می کندfixturesاستفاده خواهد شد به وسيله اين تست.آرايه نشان دهنده يك نقشه (mapping) از نام fixtureكه استفاده خواهد شد در تست براي نام كلاس مدل يا نام جدول fixture (براي كثال، ، از نام fixture ، fixture براي كلاس مدل Project ) . وقتي در حال استفاده يك نام مدل ، همانطور كه در اين مورد، جداول زمینه ای که مربوط به کلاس مدل در نظر گرفته خواهد شد به عنوان جداول fixture خواهد بود.همانطور كه ما قبلاً شرح داديم، اين مديريت fixture است كه خواهد بود مدير اين جداول اساسي و تنظیم مجدداطلاعاتبه برخی ازحالتشناخته شده هر زمان كه يك متد تست اجرا بشه.
اگر شما احتياج داريد به استفاده يك fixture براي يك جدول توسط كلاس AR نشان داده نمي شود، شما احتياج داريد به نام prefix جدول با يك دو نقطه( براي مثال، :tbl_project) براي متمايز كردن آن از نام دمدل كلاس.
نام Fixture به ما اجازه دسترسي به داده Fixture در متد تست در يك راه مناسب را ميدهد. بنابر اين، براي مثال،حالا كه ما Fixture مشخص شده در كلاس ProjectTest داريم ، ما مي تونيم دسترسي داشته باشيم به داده هايfixture مون با روش هاي زير:
// return all rows in the 'Project' fixture table
$projects = $this->projects;
// return the row whose alias is 'project1' in the `Project` fixture
table
$projectOne = $this->projects['project1'];
// If our fixture is associated with an active record, return the AR
instance representing
// the 'project1' fixture data row
$project = $this->projects('project1');
تعيين تست يك پايگاه داده
همانطور كه ما قبلاً ذكر كرديم ما نياز به جدا كردن پايگاه داده توسعمان از پايگاه داده تستمان داريم بطوري كه تست هاي ما ادامه پيدا نخواهد كرد بدون دخالت بادیتا بی اصلیمون. خوب برای این کار ما می تونیم یه دیتا بیس مصپثل دیتا یس اصلیمون بسازیم و اون رو trackstar_test بنامیم و در فایل پیکر بندی تستمون اون رو قرار بدیم تا از این به بعد هر موقه تستهای Fixture مون به اجرا در اومد تاثیری روی دیتا بیس اغصلیمون نداشته باشه. خوب حالا شما مي تونيد كامپوننت db رو كپي بگيريد از main.php فايل پيكربندي اصلي كه اضافه كرده بوديم در فصل 4 . براي كاربران mysql ، ما مي تونيم كد هاي هاي لايت شده رو به Config فايلمون تستمون اضافه كنيم:
return CMap::mergeArray(
require(dirname(__FILE__).'/main.php'),
array(
'components'=>array(
'fixture'=>array(
'class'=>'system.test.CDbFixtureManager',
),
'db'=>array(
'connectionString' =>
'mysql:host=localhost;dbname=trackstar_test',
'emulatePrepare' => true,
'username' => '[your db username]',
'password' => '[your db password]',
'charset' => 'utf8',
),
),
)
);
وقتي ما تستمون رو اجرا كنيم ، اين تست config بارگذاري مي شود، به جاي فايل Config اصلي. این فایل در واقع مجموعه ای از فایل پیکربندی اصلی با آرایه تعریف شده در این فایل پیکربندی آزمون ادغام شده. اگر اجزاء و یا همان مقادیر های پیکربندی در هر دو تعریف شده باشد، مقادیر در فایل تست ارجحیت دارند.
استفاده ازfixture ها
حالا كه ما محيط تستمون رو براي استفاده يك ديتابيس خاص تنظيم كرديم. اگر یادتون باش تست یونیتی که قبلا نوشته بودیم همه کارهی حذف ، آ÷دیت و ... رو باهم انجام میدادکه اون متد رو testCRUD() نامگذاری کرده بدیم که این راه تست چندان مناسب نیست. ولی استفاده از Fixture ها یک راه خوب برای کوچک کردن تستهای بزرگ است مثلا اگر تست Create مون به مشکل بر بخوره کل تستمون به مشکل بر میخوره و کارها انجام نمیشن حال اگر این تست یک تست بزرگ باشه یک فاجعه است. برای همین تست ها رو به اجزاء کوچکتر تبدیل میکنیم طوری که تست ها به صورت تک تک باشند.به طور معمول ما باید هر تسیت رو جدا کنیم تا تست ها به هم دیگه وابسته نباشند و روی همدیگر تاثیر نگذارند.
خوب حالا که ما همه چیز رو برای استفاده از دیتا بیس تعریف و مشخص کردیم میتونیم تست یونیت crud مون رو از هم دیگه جدا کرده و در متد های جدا قرار بدیم که این میتونه مثالهای خوبی برای چگونگی استفاده از fixture ها باشه.
بیایید بال Read کارمون رو شروع کنیم. یونین تست ProjectTest.php باز کنید و کدهای زیر رو در اون بنویسید
public function testRead()
{
$retrievedProject = $this->projects('project1');
$this->assertTrue($retrievedProject instanceof Project);
$this->assertEquals('Test Project 1',$retrievedProject->name);
ما میدانیم که این تست از ÷یش اجرا شده است، Fixture manager ریست خواهد کرد جدول tbl_project در دیتابیس trackstar_test به حالت مشخص شده به وسیله داده های Fixture . ما در اینجا به سادگی در حال خواندن سطر اول داده ها هستیم.با اشاره به نام مستعار project1 ، که بر میگردونه یک project AR رو به عنوان مثال بر اساس آن اولین ردیف از داده های تعریف شده در فایل fixtre مون که در مشسیر protected/tests/fixtures/tbl_project.php قرار دارد.همچنین کدهای Create و delete و .... رو به همین شکل پایین می تونید اضافه کنید
class ProjectTest extends CDbTestCase
{
public $fixtures=array
(
'projects'=>'Project',
);
public function testCreate()
{
//CREATE a new Project
$newProject=new Project;
$newProjectName = 'Test Project Creation';
$newProject->setAttributes(array(
'name' => $newProjectName,
'description' => 'This is a test for new project creation',
'createTime' => '2009-09-09 00:00:00',
'createUser' => '1',
'updateTime' => '2009-09-09 00:00:00',
'updateUser' => '1',
)
);
$this->assertTrue($newProject->save(false));
//READ back the newly created Project to ensure the creation
$retrievedProject=Project::model()->findByPk($newProject->id);
$this->assertTrue($retrievedProject instanceof Project);
$this->assertEquals($newProjectName,$retrievedProject->name);
}
public function testRead()
{
$retrievedProject = $this->projects('project1');
$this->assertTrue($retrievedProject instanceof Project);
$this->assertEquals('Test Project 1',$retrievedProject->name);
}
public function testUpdate()
{
$project = $this->projects('project2');
$updatedProjectName = 'Updated Test Project 2';
$project->name = $updatedProjectName;
$this->assertTrue($project->save(false));
//read back the record again to ensure the update worked
$updatedProject=Project::model()->findByPk($project->id);
$this->assertTrue($updatedProject instanceof Project);
$this->assertEquals($updatedProjectName,$updatedProjec t->name);
}
public function testDelete()
{
$project = $this->projects('project2');
$savedProjectId = $project->id;
$this->assertTrue($project->delete());
$deletedProject=Project::model()->findByPk($savedProjectId);
$this->assertEquals(NULL,$deletedProject);
}
}
برنامه ریزی تکرار
ما در حال حاضر توانایی ایجاد و لیست پروژه ها رو اریم ،ولی این پروژه در عین حال قادر به مهار هیچ جیزی نیست.در انتهای این فصل ما میخواهیم برناممون می خواهیم که بیشتر کارها رو انجام بده .ما همچنین می خواهیم محدود کنیم عملیات خام مسائل رو در چارچوب یک پروژه خاص .که مسائل متعلق به پروژه است.کاربر باید انتخاب بکنه از پروژه های موجود قبل از این که قادر به انجام هر گونه عملیات خام در مسائل مربوط به پروژه باشد.
به منظور دستیابی بهقبلاهدافمشخص شده،ما نیاز به شناسایی تمام موارد ریزی داریم که در این برنامه دخیل هستند.فهرست زیر به تشریح این آیتمها میپردازه:
· طراحی شمای پایگاه داده، و ساختن اشیاء برای حمایت از مسائل مربوط به پروژه
· ایجاد کلاس های مدل Yii که اجازه می دهد برنامه به راحتی با جدول پایگاه داده (بازدید کنندگان) تعامل کند.
· ایجاد کلاس کنترلر که قابلیت انجام عملیات زیر رو به ما میده:
1- ساخت مسائل جدید
2- بیرون کشیدن یک لیست از مسائل موجود در داخل یک پروژ از دیتابیس
3- آ÷دیت و ادیت کردن مسائل موجود
4- حذف مسائل موجود
· ساخت ویو برای ارائه اینترفیس مناسب برای کاربر
این اطلااعات برای شروع کار ما کافی می باشد.بعد از این که تستمون رو اجرا کردیم ، بد میریم سر تغیراتی که باید در دیتا بیسمون انجام بدیم.
آجرا کردن ادامه تست ها
برای ادامه کار بیایید همه تستهامون ر با هم انجام بدیم این کار رو مثل قبل انجام بدید از گفتن این قسمت صرف نظر میکنیم
.
طراحی طرح
اگر یادتون باشه در فصل های قبل طرحی رو دادیم که شامل نوع،مالک ، درخواست کننده، وضعیت، و توضیحاتی بود .همچنین وقتی ما جدول tbl_project رو ساختیم چند تا ستون وجود داشتند که از این قرار بودند زمان،تاریخ و این که یک نفر چه وقت این جدول رو آپدیت کرده.اگرچه types, owners, requesters, and statuses موجودیت خودشون رو دارند.ما مدل های خودمون رو قابل انعطاف و توسعه پذیر نگه میداریم،به همین دلیل برخی از مدل ها رو به طور جداگانه خواهیم داشت.
مالک(Owners) و درخواست کننده (requesters) هر دو کاربرانی از سیستم هستند و اشاره خواهند کر به سطری در یک جدول که که اونو tbl_user نامگذاری خواهیم کرد.
ما در حال حاضر معرفی میکنی ایده ای از یک کاربر که در جدول tbl_project وجود دارد که ستون های create_user_id و update_user_id در جدول tbl_project میباشد .همانطور که معلومه اسن دو ستون به ستونهای خارجی در جدولی دیگر اشاره دارند که ستونهایی از یک جلود مثل جدول کاربران می باشد.
فیلدهای owner_id و requestor_id در جدول tbl_issue نیز ارتباط خواهند داشت با جدولی دیگر در بیرون از خود به نام جدول tbl_user.
ما بطور مشابه می توانیم مدل های type و status رو به همین شیوه پیاده سازی کنیم، اگر چه تا زمانی کارهامون خیلی پیچیده نشده میتونیم اینها رو در tbl_issue به صورت اعداد نگهداری کنیم که بعدا اونها رو به نامهاب مختلف ذخیره و تبدیل کنیم.
تعریفبرخی ازروابط
خوب بریم برای ساخت جدول Tbl_user همچنبن ما به روابط بین این جدول و جدول پروژه ها نیاز داریم.قبلا وقتی ما معرفی کرده بودیم برنامه trackstar رو در فصل 3 ما مشخص کردیم که کاربران در ارتباط هستند با یک یا چندین پروژه .و همچنین بنابر این پروژه ها میتونن کاربران زیادی داشته باشند و کاربان نیز می تونند با پروژه های زیادی دی ارتباط باشندما این رو یک ارتباط many-to-many ما بین پروژه ها و کاربران مینامیم.یک راه ساده برای مدل many-to-many ارتباط در یک دیتا بیس رابطه ای است برای استفاده از ارتباط و یا انتساب جداول. پس ما احتیاج داریم که این جدول رو به مدلمون اضافه کنیم.شکل زیر روابط بین users ، projects و issues یا همون مسائل رو ترسیم میکنه.
پروژه می تواند هیچ و یا تعداد زیادی کاربر داشته باشد. یک کاربر احتیاج داره به ارتباط با حداقل یک پروژه ، اما میتونه با چندبن پروژه در ارتباط باشه issues متعلق به یک وتنها یک پروژه میتونه باشه در حالی که پروژه ها می تواند صفر تا بسیاری از مسائل را داشته باشد.