рдЕрдм рдореИрдВ Yii- рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдореЙрдбрд▓ рд╡рд┐рдХрд╛рд╕ рдХреЗ рд▓рд┐рдП TDD рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХреА рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛ред
рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ "рдкрд░реАрдХреНрд╖рдг" рд╡рд┐рд╖рдп рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдореИрдиреБрдЕрд▓ (
http://yiiframework.ru/doc/guide/ru/test.overview ) рд╕реЗ рдкрдврд╝рд╛ рдЧрдпрд╛ рдерд╛ред
рдЗрд╕рд▓рд┐рдП, рдкрд░реНрдпрд╛рд╡рд░рдг рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЕрдм рд╣рдорд╛рд░рд╛ рдХрд╛рдо рд╢реНрд░реЗрдгреА рдФрд░ рдЙрддреНрдкрд╛рджреЛрдВ (рд╢реНрд░реЗрдгреА, рдЙрддреНрдкрд╛рдж) рдХреЗ рдореЙрдбрд▓ рдмрдирд╛рдирд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдкрд░реАрдХреНрд╖рдгреЛрдВ рд╕реЗ рдврдВрдХрдирд╛ рд╣реЛрдЧрд╛ред
рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╢реНрд░реЗрдгреА рддрд╛рд▓рд┐рдХрд╛ рд╣реИ:
- PARENT_ID
- рдирд╛рдо
- рд╡рд┐рд╡рд░рдг
- рд╕реНрдерд┐рддрд┐
рдЙрддреНрдкрд╛рдж рддрд╛рд▓рд┐рдХрд╛:
- category_id
- рдирд╛рдо
- рд╡рд┐рд╡рд░рдг
- рдХреАрдордд
- рд╕реНрдерд┐рддрд┐
Gii рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдЗрди рддрд╛рд▓рд┐рдХрд╛рдУрдВ рд╕реЗ рдореЙрдбрд▓ рдмрдирд╛рддреЗ рд╣реИрдВред рдпреЗ рд╢реНрд░реЗрдгреА рдФрд░ рдЙрддреНрдкрд╛рдж рдореЙрдбрд▓ рд╣реЛрдВрдЧреЗред
рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдореЙрдбрд▓ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рд╣рдо CDbTestCase рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдХрдХреНрд╖рд╛рдПрдВ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рд▓реЗрдВрдЧреЗред
рд╢реНрд░реЗрдгреА рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд░реАрдХреНрд╖рдг рд╡рд░реНрдЧ рдмрдирд╛рдПрдВред рдЕрдВрджрд░, рд╣рдо рдкрд░реАрдХреНрд╖рдг рд╢реНрд░реЗрдгреА рдХреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП "рд╢реНрд░реЗрдгреА" рд╕рдВрдкрддреНрддрд┐ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рд╕реЗрдЯрдЕрдк () рд╡рд┐рдзрд┐ рдореЗрдВ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рд▓рд┐рдЦрддреЗ рд╣реИрдВред
class CategoryTest extends CDbTestCase { protected $category; protected function setUp() { parent::setUp(); $this->category = new Category(); } }
рд╕рднреА рдореЙрдбрд▓реЛрдВ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреНрд╖реЗрддреНрд░ рд╕рддреНрдпрд╛рдкрди рд╣реИ, рдФрд░ рд╣рдо рдЗрд╕рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВрдЧреЗред
рдЖрдЗрдП рдмрддрд╛рддреЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдорд╛рдиреНрдпрддрд╛ рдирд┐рдпрдо рдореМрдЬреВрдж рд╣реЛрдВрдЧреЗ:
- рд╢реАрд░реНрд╖рдХ рдПрдХ рдЖрд╡рд╢реНрдпрдХ рдХреНрд╖реЗрддреНрд░ рд╣реИ
- рд╢реАрд░реНрд╖рдХ рд▓рдВрдмрд╛рдИ рдЕрдзрд┐рдХрддрдо 150 рд╡рд░реНрдг
- рдпрджрд┐ рднрд░рд╛ рд╣реИ, рддреЛ рдорд╛рддрд╛-рдкрд┐рддрд╛ рдХреЛ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдореМрдЬреВрдж рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП
- рд╡рд░реНрдгрди рд▓рдВрдмрд╛рдИ рдЕрдзрд┐рдХрддрдо 4000 рд╡рд░реНрдг
- рд╕реНрдерд┐рддрд┐ рдПрдХ рдЖрд╡рд╢реНрдпрдХ рдХреНрд╖реЗрддреНрд░ рд╣реИ
- рд╕реНрдЯреЗрдЯрд╕ рдореЗрдВ рджрд┐рдП рдЧрдП рд▓рд┐рд╕реНрдЯ рдореЗрдВ рд╕реЗ рд╡реИрд▓реНрдпреВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП
рддреЛ, "рд╢реАрд░реНрд╖рдХ рдПрдХ рдЖрд╡рд╢реНрдпрдХ рдХреНрд╖реЗрддреНрд░ рд╣реИред" рдЯреАрдбреАрдбреА рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдд, рд╣рдо рдкрд╣рд▓реЗ рдПрдХ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрддреЗ рд╣реИрдВред
public function testTitleIsRequired() { $this->category->title = ''; $this->assertFalse($this->category->validate(array('title'))); }
- рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдирд╛рдо рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╣рдореЗрдВ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╡рд┐рдзрд┐ рдкрд░реАрдХреНрд╖рдг рд╣реИред
- рдЕрдВрджрд░, рд╣рдо рдПрдХ рд░рд┐рдХреНрдд рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рд╢реАрд░реНрд╖рдХ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ, рд╕рддреНрдпрд╛рдкрди рдЪрд▓рд╛рддреЗ рд╣реИрдВ рдФрд░ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдкрд╛рд░рд┐рдд рдирд╣реАрдВ рд╣реБрдЖред
рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдкрд░реАрдХреНрд╖рдг рд▓рд╛рд▓ рд╣реИред рд╣рдо рд╕рддреНрдпрд╛рдкрди рд▓рд┐рдЦрддреЗ рд╣реИрдВред
public function rules() { return array( array('title', 'required'), ); }
рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдкрд░реАрдХреНрд╖рдг рд╣рд░рд╛ рд╣реИред рд░рд┐рдлреИрдХреНрдЯрд░рд┐рдВрдЧ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЕрдЧрд▓реЗ рдкрд░реАрдХреНрд╖рдг рдкрд░ рдЬрд╛рдПрдВред
рд╢реАрд░реНрд╖рдХ рд▓рдВрдмрд╛рдИ рдЕрдзрд┐рдХрддрдо 150 рд╡рд░реНрдг
public function testTitleMaxLengthIs150() { $this->category->title = generateString(151); $this->assertFalse($this->category->validate(array('title'))); $this->category->title = generateString(150); $this->assertTrue($this->category->validate(array('title'))); }
рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдкрд░реАрдХреНрд╖рдг рд▓рд╛рд▓ рд╣реИред рдЖрдкрдХреЛ рд╕рддреНрдпрд╛рдкрди рдЬреЛрдбрд╝рдХрд░ рдкрд░реАрдХреНрд╖рдг рдХреЛ рд╣рд░рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
public function rules() { return array( array('title', 'required'), array('title', 'length', 'max' => 150) ); }
рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдкрд░реАрдХреНрд╖рдг рд╣рд░рд╛ рд╣реИ, рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИред
рдЕрдм рд╣рдо рдореЙрдбрд▓ рд╕рдВрдмрдВрдзреЛрдВ рдХреЛ рдорд╛рдиреНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред "рд╢реНрд░реЗрдгреА" рдореЙрдбрд▓ рдореЗрдВ, рд╣рдорд╛рд░рд╛ рдорддрд▓рдм рдПрдХ "рдорд╛рддрд╛-рдкрд┐рддрд╛" рд░рд┐рд╢реНрддреЗ рдХреЗ рдЕрд╕реНрддрд┐рддреНрд╡ рд╕реЗ рд╣реИред
рд▓рд┐рдВрдХ рдкрд░реАрдХреНрд╖рдг рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЬреБрдбрд╝рдирд╛рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рд╡рд╛рдВрдЫрд┐рдд рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдлрд╝рд┐рдХреНрдЪрд░ рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдВред
рдореБрдЭреЗ рдЖрдкрдХреЛ рдпрд╛рдж рджрд┐рд▓рд╛рдирд╛ рд╣реИ рдХрд┐ рдлрд╝рд┐рдХреНрдЪрд░ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдЙрд╕реА рддрд░рд╣ рдирд╛рдорд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ рдлрд╝рд┐рдХреНрдЪрд░ рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
return array( 'sample' => array( 'id' => 1, ), 'sample2' => array( 'id' => 2, 'parent_id' => 1 ) );
рд╣рдо рдкрд░реАрдХреНрд╖рдг рд╕реЗ рдЬреБрдбрд╝рд╛рд╡ рддрдп рдХрд░рддреЗ рд╣реИрдВред
class CategoryTest extends CDbTestCase { public $fixtures = array( 'categories' => 'Category' ); ...
рд╣рдо рдХрдиреЗрдХреНрд╢рди рдХреА рдЬрд╛рдВрдЪ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦ рд░рд╣реЗ рд╣реИрдВред
public function testBelongsToParent() { $category = Category::model()->findByPk(2); $this->assertInstanceOf('Category', $category->parent); }
рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдкрд░реАрдХреНрд╖рдг рд▓рд╛рд▓ рд╣реИред рдореЙрдбрд▓ рдореЗрдВ рд░рд┐рд╢реНрддреЗ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред
public function relations() { return array( 'parent' => array(self::BELONGS_TO, __CLASS__, 'parent_id'), ); }
рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдкрд░реАрдХреНрд╖рдг рд╣рд░рд╛ рд╣реИред
рдЬреБрдбрд╝рдирд╛рд░ рдХреЗ рдЖрдЧрдорди рдХреЗ рд╕рд╛рде, рдПрдХ рд╕рдорд╕реНрдпрд╛ рдкреИрджрд╛ рд╣реБрдИред CDBTestCase рд╡рд░реНрдЧ рдХрд╛ рд╕реЗрдЯрдЕрдк () рд╡рд┐рдзрд┐ рд╕рдВрд╕рд╛рдзрди-рдЧрд╣рди рд╕реНрдерд┐рд░рддрд╛ рд▓реЛрдбрд┐рдВрдЧ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рдЬреБрдбрд╝рдирд╛рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рди рд╣реЛред рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдЗрд╕ рддрд░рд╣ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
class DbTestCase extends CDbTestCase { private static $_loadFixturesFlag = false; protected function setUp() { if (!self::$_loadFixturesFlag && is_array($this->fixtures)) { $this->loadFixtures(); self::$_loadFixturesFlag = true; } } public function loadFixtures($fixtures = null) { if ($fixtures === null) { $fixtures = $this->fixtures; } $this->getFixtureManager()->load($fixtures); } }
рд╣рдордиреЗ CDbTestCase рдХрд╛ рдПрдХ рд╡рдВрд╢рдЬ рдмрдирд╛рдпрд╛ рдФрд░ рдЗрд╕реЗ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛ред рдЕрдм рдЬреБрдбрд╝рдирд╛рд░ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╣рдо рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдореЗрдВ рд╕реНрдерд┐рд░рддрд╛ рдбреЗрдЯрд╛ рдмрджрд▓рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдЙрдиреНрд╣реЗрдВ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд▓реЛрдбрдлрд┐рдХреНрд╕рдЪрд░реНрд╕ () рд╡рд┐рдзрд┐ рд╕реЗ рдХреЙрд▓ рдХрд░рдХреЗ рдкреБрдирдГ рд▓реЛрдб рдХрд░рддреЗ рд╣реИрдВред
рдЕрдм рдореИрдВ "рд╢реНрд░реЗрдгреА" рдФрд░ "рд╢реНрд░реЗрдгреАрдЯреЗрд╕реНрдЯ" рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рдЕрдВрддрд┐рдо рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рджреВрдВрдЧрд╛ред рдЙрддреНрдкрд╛рдж рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рд▓реЗрдЦрди рдкрд░реАрдХреНрд╖рдг рд╣реЛрдорд╡рд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рд░рд╣рддрд╛ рд╣реИред
class CategoryTest extends DbTestCase { protected $category; protected function setUp() { parent::setUp(); $this->category = new Category(); } public function testAllAttributesHaveLabels() { $attributes = array_keys($this->category->attributes); foreach ($attributes as $attribute) { $this->assertArrayHasKey($attribute, $this->category->attributeLabels()); } } public function testBelongsToParent() { $category = Category::model()->findByPk(2); $this->assertInstanceOf('Category', $category->parent); } public function testTitleIsRequired() { $this->category->title = ''; $this->assertFalse($this->category->validate(array('title'))); } public function testTitleMaxLengthIs150() { $this->category->title = generateString(151); $this->assertFalse($this->category->validate(array('title'))); $this->category->title = generateString(150); $this->assertTrue($this->category->validate(array('title'))); } public function testParentIdIsExist() { $this->category->parent_id = 'not-exist-value'; $this->assertFalse($this->category->validate(array('parent_id'))); $this->category->parent_id = 1; $this->assertTrue($this->category->validate(array('parent_id'))); } public function testDescriptionMaxLengthIs4000() { $this->category->description = generateString(4001); $this->assertFalse($this->category->validate(array('description'))); $this->category->description generateString(4000); $this->assertTrue($this->category->validate(array('description'))); } public function testStatusIsRequired() { $this->category->status = ''; $this->assertFalse($this->category->validate(array('status'))); } public function testStatusExistsInStatusList() { $this->category->status = 'not-in-list-value'; $this->assertFalse($this->category->validate(array('status'))); $this->category->status = array_rand($this->category->getStatusList()); $this->assertTrue($this->category->validate(array('status'))); } public function testSafeAttributesOnSearchScenario() { $category = new Category('search'); $mustBeSafe = array('title', 'description'); $safeAttrs = $category->safeAttributeNames; sort($mustBeSafe); sort($safeAttrs); $this->assertEquals($mustBeSafe, $safeAttrs); } } class Category extends CActiveRecord { const STATUS_PUBLISH = 1; const STATUS_DRAFT = 2; public static function getStatusList($key = null) { $arr = array( self::STATUS_PUBLISH => 'Publish', self::STATUS_DRAFT => 'Draft', ); return $key === null ? $arr : $arr[$key]; } public function tableName() { return '{{categories}}'; } public function rules() { return array( array('title, status', 'required'), array('title', 'length', 'max' => 150), array('parent_id', 'exist', 'className' => __CLASS__, 'attributeName' => 'id'), array('description', 'length', 'max' => 4000), array('status', 'in', 'range' => array_keys($this->getStatusList())), array('title, description', 'safe', 'on' => 'search') ); } public function relations() { return array( 'parent' => array(self::BELONGS_TO, __CLASS__, 'parent_id'), ); } public function attributeLabels() { return array( 'id' => 'ID', 'parent_id' => 'Parent ID', 'title' => 'Title', 'description' => 'Description', 'status' => 'Status', ); } public function search() { $criteria=new CDbCriteria; $criteria->compare('title',$this->title,true); $criteria->compare('description',$this->description,true); return new CActiveDataProvider($this, array( 'criteria'=>$criteria, )); }