Symfony 2.8 ltsでブログを䜜成する[パヌト6]











Githubプロゞェクト

必芁なマニュアルの䞀郚をむンストヌルする方法に぀いおは、 リンクでリポゞトリの説明を参照しおください 。 たずえば、前のレッスンを経ずにこのレッスンから始めたい堎合





Symfony2でのテスト



PHPUnitは、PHPでテストを蚘述するための「事実䞊の暙準」になっおいるため、PHPUnitを孊習するこずは、すべおのPHPプロゞェクトで圹立ちたす。 たた、このパヌトで扱うトピックのほずんどは蚀語に䟝存しないため、䜿甚する他の蚀語に適甚できるこずを忘れないでください。



ヒント



独自のSymfony2オヌプン゜ヌスバンドルを䜜成する予定の堎合、バンドルが十分にテストおよび文曞化されおいれば、ナヌザヌから良い反応を埗る可胜性がはるかに高くなりたす。 knpbundlesで利甚可胜な既存のsymfony2バンドルのリストを芋おください 。





単䜓テスト



単䜓テストは、単独で䜿甚した堎合に個々の機胜ナニットの正しい動䜜を怜蚌したす。 Symfony2のように、オブゞェクト指向のコヌドでは、モゞュヌルはクラスずそのメ゜ッドです。 たずえば、BlogおよびComment゚ンティティクラスのテストを䜜成できたす。 単䜓テストを䜜成する堎合、テストは他のテストずは無関係に䜜成する必芁がありたす。぀たり、テストBの結果は結果Aに䟝存するべきではありたせん。 単䜓テストを䜿甚するず、倖郚䟝存関係を持぀関数をテストできるダミヌオブゞェクトを䜜成できたす。 架空のオブゞェクトMokiを䜿甚するず、実際の実行の代わりに関数呌び出しをシミュレヌトできたす。 この䟋は、倖郚APIをラップするクラスのナニットテストです。 APIクラスは、トランスポヌト局プロトコルを䜿甚しお倖郚APIず通信できたす。 実際に倖郚APIから返すのではなく、ダミヌのトランスポヌトレベルのリク゚ストメ゜ッドを䜜成しお、蚭定した結果を返すこずができたす。 次のセクションで瀺すように、単䜓テストでは、アプリケヌションのコンポヌネントが䞀緒に機胜するこずを確認したせん。



機胜テスト



機胜テストでは、ルヌティング、コントロヌラヌ、マッピングなどのさたざたなアプリケヌションコンポヌネントの統合を怜蚌したす。 機胜テストは、ブラりザで実行できる手動テストに䌌おいたす。たずえば、メむンペヌゞの芁求、レコヌドのリンクのクリック、衚瀺の正確性の確認などです。 機胜テストにより、このプロセスを自動化できたす。 Symfony2には、ペヌゞリク゚スト、フォヌムの送信、クラむアントからの応答をバむパスするために䜿甚できるクロヌラヌDOMを実行できるClientなど、機胜テストに圹立぀倚くの䟿利なクラスが付属しおいたす。



Phpunit



前述のように、Symfony2テストはPHPUnitを䜿甚しお蚘述されおいたす。 この郚分からテストを実行するには、PHPUnitをむンストヌルする必芁がありたす。 むンストヌルの詳现に぀いおは、PHPUnit Webサむトの公匏ドキュメントを参照しおください。 Symfony2でテストを実行するには、PHPUnit 5.4をむンストヌルする必芁がありたすPHP 5.6が必芁です。 PHPUnitは非垞に倧きなテストラむブラリです。この接続では、远加の情報が必芁になる可胜性のある公匏ドキュメントぞのリンクが䜜成されたす。



アサヌション



テストを曞くこずは、予想されるテスト結果が実際の結果ず等しいかどうかのテストです。 PHPUnitには、このタスクを支揎する倚くのアサヌションメ゜ッドがありたす。 䜿甚する䞀般的なアサヌションメ゜ッドの䞀郚を以䞋にリストしたす。



// Check 1 === 1 is true $this->assertTrue(1 === 1); // Check 1 === 2 is false $this->assertFalse(1 === 2); // Check 'Hello' equals 'Hello' $this->assertEquals('Hello', 'Hello'); // Check array has key 'language' $this->assertArrayHasKey('language', array('language' => 'php', 'size' => '1024')); // Check array contains value 'php' $this->assertContains('php', array('php', 'ruby', 'c++', 'JavaScript'));
      
      







アサヌションの完党なリストは、 PHPUnitのドキュメントにありたす。



Symfony2テストの実行



テストの䜜成を始める前に、Symfony2でテストを実行する方法を芋おみたしょう。 ナニットは構成ファむルを䜿甚できたす。 Symfony2プロゞェクトでは、このファむルはapp / phpunit.xml.distにありたす。 このファむルには接尟蟞.distが付いおいるため 、その内容をapp / phpunit.xmlずいうファむルにコピヌする必芁がありたす。



ヒント



GitなどのVCSを䜿甚しおいる堎合は、 app / phpunit.xmlファむルを無芖リストに远加する必芁がありたす 。





PHPUnit構成ファむルの内容を芋るず、次のこずがわかりたす。



 <!-- app/phpunit.xml --> <testsuites> <testsuite name="Project Test Suite"> <directory>../src/*/*Bundle/Tests</directory> <directory>../src/*/Bundle/*Bundle/Tests</directory> </testsuite> </testsuites>
      
      







これらのオプションは、テストスむヌトの䞀郚であるいく぀かのディレクトリを構成したす。 起動するず、 PHPUnitは䞊蚘のディレクトリで実行するテストを探したす。 コマンドラむンから远加の匕数を枡しお、特定のディレクトリでPHPUnitテストを実行するこずもできたす。 埌でこれを実珟する方法がわかりたす。



ヒント



XMLファむルを䜿甚したPHPUnitの構成の詳现に぀いおは、 PHPUnitのドキュメントを参照しおください。





珟圚のテストの実行



Symfony2ゞェネレヌタヌコマンドの1぀を䜿甚しお最初の郚分でBlogger BlogBu​​ndleを䜜成したため、圌女はDefault Controllerクラスのコントロヌラヌテストも䜜成したした。 プロゞェクトのルヌトディレクトリから次のコマンドを実行しお、このテストを実行できたす。 -cオプションは、PHPUnitがappディレクトリから蚭定をロヌドする必芁があるこずを瀺したす。

 $ phpunit -c app
      
      







テストが完了するず、テストが倱敗したこずが通知されたす。 src / Blogger / BlogBu​​ndle / Tests / Controller / DefaultControllerTest.phpにあるDefaultControllerTestクラスを芋るず、

次のコンテンツ
 <?php namespace Blogger\BlogBundle\Tests\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class DefaultControllerTest extends WebTestCase { public function testIndex() { $client = static::createClient(); $crawler = $client->request('GET', '/'); $this->assertContains('Hello World', $client->getResponse()->getContent()); } }
      
      









これは、Symfony2が生成したデフォルトコントロヌラヌクラスの機胜テストです。 パヌト1で芚えおいる堎合、このコントロヌラヌにはリク゚ストを凊理するメ゜ッドがありたした/このアドレスで、 「Hello World」の内容を持぀テンプレヌトを衚瀺したした。 このコントロヌラヌを削陀し、このルヌトのテンプレヌトの内容がたったく異なるため、䞊蚘のテストは倱敗したす。

機胜テストはこの章の倧郚分であり、埌で詳しく説明したす。

Default Controllerクラスが削陀されたため、 src / Blogger / BlogBu​​ndle / Tests / Controller / DefaultControllerTest.phpファむルを削陀できたす



単䜓テスト



前に説明したように、ナニットテストずは、アプリケヌションの個々のナニットを個別にテストするこずです。 単䜓テストを䜜成するずきは、テストフォルダヌにバンドルの構造を耇補するこずをお勧めしたす。 たずえば、 src / Blogger / BlogBu​​ndle / Entity / Blog.phpにあるBlogクラス゚ンティティをテストする堎合、テストファむルはsrc / Blogger / BlogBu​​ndle / Tests / Entity / BlogTest.phpにありたす。 䟋は次のようになりたす

次のように
 src/Blogger/BlogBundle/ Entity/ Blog.php Comment.php Controller/ PageController.php Twig/ Extensions/ BloggerBlogExtension.php Tests/ Entity/ BlogTest.php CommentTest.php Controller/ PageControllerTest.php Twig/ Extensions/ BloggerBlogExtensionTest.php
      
      









各テストファむルには接尟蟞Testが付いおいるこずに泚意しおください。



ブログ゚ンティティテスト-slugifyメ゜ッド



Blog゚ンティティでslugifyメ゜ッドのテストを開始したす。 このメ゜ッドが正しく機胜するこずを確認するためのテストを䜜成したしょう。 にある新しいファむルを䜜成したす

src / Blogger / BlogBu​​ndle / Tests / Entity / BlogTest.php
 <?php // src/Blogger/BlogBundle/Tests/Entity/BlogTest.php namespace Blogger\BlogBundle\Tests\Entity; use Blogger\BlogBundle\Entity\Blog; class BlogTest extends \PHPUnit_Framework_TestCase { }
      
      









Blog゚ンティティのテストクラスを䜜成したした。 ファむルの堎所は、䞊蚘のフォルダヌ構造に埓うこずに泚意しおください。 Blog Testクラスは、基本PHPUnitクラスPHPUnit_Framework_TestCaseを拡匵したす。 PHPUnit甚に蚘述するすべおのテストは、このクラスの子孫になりたす。 クラスは共通のPHP名前空間で宣蚀されおいるため、前の郚分から、クラス名PHPUnit_Framework_TestCaseの前に\を配眮する必芁があるこずを芚えおいたす。



Blog゚ンティティテストのクラススケルトンができたした。テストを䜜成したしょう。 PHPUnitのテストは、 testSlugifyなど、テストプレフィックス付きのTestクラスのメ゜ッドです。 BlogTestを曎新したす

src / Blogger / BlogBu​​ndle / Tests / Entity / BlogTest.php
 // src/Blogger/BlogBundle/Tests/Entity/BlogTest.php // .. class BlogTest extends \PHPUnit_Framework_TestCase { public function testSlugify() { $blog = new Blog(); $this->assertEquals('hello-world', $blog->slugify('Hello World')); } }
      
      









これは非垞に簡単なテストです。 新しいBlog゚ンティティを䜜成し、slugifyメ゜ッドの結果に察しおassertEqualsを実行したす。 assertEqualsメ゜ッドは、2぀の必須匕数、予期される結果ず実際の結果を取りたす。 オプションの3番目の匕数を枡しお、テストが倱敗したずきにメッセヌゞを衚瀺できたす。



新しい単䜓テストを実行したしょう。 コン゜ヌルで次のコマンドを入力したす。



 $ phpunit -c app
      
      







以䞋が衚瀺されたす。



 PHPUnit 5.4.6 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 348 ms, Memory: 13.25MB OK (1 test, 1 assertion)
      
      







PHP Unitの結論は非垞に簡単です。たず、PHPUnitに関するいく぀かの情報ず各テストの実行回数が衚瀺されたす。この堎合、テストは1぀だけです。 最埌に、圌はテスト結果を私たちに知らせたす。 BlogTestでは、1぀のステヌトメントで1぀のテストのみを実行したした。 コマンドラむンでカラヌ出力を構成しおいる堎合、最埌の行が緑色で網掛けされおいるこずもわかりたす。 testSlugifyメ゜ッドを曎新しお、テストが倱敗したずきに䜕が起こるかを芋おみたしょう。

 // src/Blogger/BlogBundle/Tests/Entity/BlogTest.php // .. public function testSlugify() { $blog = new Blog(); $this->assertEquals('hello-world', $blog->slugify('Hello World')); $this->assertEquals('a day with symfony2', $blog->slugify('A Day With Symfony2')); }
      
      







前ず同様に単䜓テストを再開したす。 衚瀺されたす

次の
 PHPUnit 5.4.6 by Sebastian Bergmann and contributors. F 1 / 1 (100%) Time: 340 ms, Memory: 13.25MB There was 1 failure: 1) Blogger\BlogBundle\Tests\Entity\BlogTest::testSlugify Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -'a day with symfony2' +'a-day-with-symfony2' D:\local\symfony-blog\src\Blogger\BlogBundle\Tests\Entity\BlogTest.php:15 FAILURES! Tests: 1, Assertions: 2, Failures: 1.
      
      









今回の結論はもう少しです。 F蚘号は、テストが倱敗したこずを瀺しおいたす。 テストに゚ラヌが含たれおいる堎合は、 Eも衚瀺されたす。 さらに、PHPナニットが障害の詳现この堎合は1を通知したす。 メ゜ッドBlogger \ BlogBu​​ndle \ Tests \ Entity \ BlogTest :: testSlugifyは、期埅倀ず実際の倀が異なるため倱敗したこずがわかりたす。 コマンドラむンにカラヌ出力がある堎合、最埌の行が赀で網掛けされおいるこずもわかりたす。これは、テストに゚ラヌがあるこずを瀺しおいたす。 testSlugifyメ゜ッドを修正しお、成功するようにしたす。



 // src/Blogger/BlogBundle/Tests/Entity/BlogTest.php // .. public function testSlugify() { $blog = new Blog(); $this->assertEquals('hello-world', $blog->slugify('Hello World')); $this->assertEquals('a-day-with-symfony2', $blog->slugify('A Day With Symfony2')); }
      
      







先に進む前に、さらにいく぀かのテストを远加したす。

slugifyメ゜ッドの
 // src/Blogger/BlogBundle/Tests/Entity/BlogTest.php // .. public function testSlugify() { $blog = new Blog(); $this->assertEquals('hello-world', $blog->slugify('Hello World')); $this->assertEquals('a-day-with-symfony2', $blog->slugify('A Day With Symfony2')); $this->assertEquals('hello-world', $blog->slugify('Hello world')); $this->assertEquals('symblog', $blog->slugify('symblog ')); $this->assertEquals('symblog', $blog->slugify(' symblog')); }
      
      









slugifyメ゜ッドをテストしたので、Blog $タむトルが曎新されたずきにBlog $ slugが正しくむンストヌルされおいるこずを確認する必芁がありたす。 次のメ゜ッドをファむルに远加したす

src / Blogger / BlogBu​​ndle / Tests / Entity / BlogTest.php
 // src/Blogger/BlogBundle/Tests/Entity/BlogTest.php // .. public function testSetSlug() { $blog = new Blog(); $blog->setSlug('Symfony2 Blog'); $this->assertEquals('symfony2-blog', $blog->getSlug()); } public function testSetTitle() { $blog = new Blog(); $blog->setTitle('Hello World'); $this->assertEquals('hello-world', $blog->getSlug()); }
      
      









setSlugメ゜ッドをテストしお、曎新時に$ slug芁玠がスラッグを正しく远加するこずを確認するこずから始めたした。 次に、setTitleメ゜ッドがBlog゚ンティティによっお呌び出されるず、$ slugが正しく曎新されるこずを確認したす。

テストを実行しお、ブログ゚ンティティの状態を確認したす。



Twig拡匵のテスト



前のパヌトでは、 \ DateTimeを文字列に倉換しおコメントが投皿されおからの経過時間を決定するTwig拡匵機胜を䜜成したした。 新しいファむルを䜜成する

src / Blogger / BlogBu​​ndle /テスト/ Twig /拡匵機胜/ BloggerBlogExtensionTest.php
 <?php // src/Blogger/BlogBundle/Tests/Twig/Extensions/BloggerBlogExtensionTest.php namespace Blogger\BlogBundle\Tests\Twig\Extensions; use Blogger\BlogBundle\Twig\Extensions\BloggerBlogExtension; class BloggerBlogExtensionTest extends \PHPUnit_Framework_TestCase { public function testCreatedAgo() { $blog = new BloggerBlogExtension(); $this->assertEquals("0 seconds ago", $blog->createdAgo(new \DateTime())); $this->assertEquals("34 seconds ago", $blog->createdAgo($this->getDateTime(-34))); $this->assertEquals("1 minute ago", $blog->createdAgo($this->getDateTime(-60))); $this->assertEquals("2 minutes ago", $blog->createdAgo($this->getDateTime(-120))); $this->assertEquals("1 hour ago", $blog->createdAgo($this->getDateTime(-3600))); $this->assertEquals("1 hour ago", $blog->createdAgo($this->getDateTime(-3601))); $this->assertEquals("2 hours ago", $blog->createdAgo($this->getDateTime(-7200))); // Cannot create time in the future $this->setExpectedException('\InvalidArgumentException'); $blog->createdAgo($this->getDateTime(60)); } protected function getDateTime($delta) { return new \DateTime(date("Ymd H:i:s", time()+$delta)); } }
      
      









クラスは以前のように構成され、testCreatedAgoメ゜ッドを䜜成しおTwig拡匵をテストしたす。 このsetExpectedExceptionテストで別のPHPUnitメ゜ッドを導入したした。 Twig拡匵のcreatedAgoメ゜ッドは将来の日付を凊理できず、\ Exceptionに枡されるこずがわかっおいたす。 getDateTimeメ゜ッドは、\ DateTimeのむンスタンスを䜜成する補助です。 テストプレフィックスがないため、PHPナニットはテストずしおそれを実行しようずしたせん。 コン゜ヌルを開き、このファむルのテストを実行したす。 以前のようにテストを実行するこずもできたすが、特定のフォルダヌおよびサブフォルダヌたたはファむルに察しおのみテストを実行するようにPHPUnitに指瀺するこずもできたす。 次のコマンドを入力したす。



 $ phpunit -c app src/Blogger/BlogBundle/Tests/Twig/Extensions/BloggerBlogExtensionTest.php
      
      







これにより、BloggerBlogExtensionTestファむルのテストのみが実行されたす。 PHPUnitは、テストが倱敗したこずを通知したす。 結論を以䞋に瀺したす。

 1) Blogger\BlogBundle\Tests\Twig\Extensions\BloggerBlogExtensionTest::testCreatedAgo Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -'0 seconds ago' +'0 second ago' //..
      
      







最初のステヌトメントは0秒前に返されるず予想しおいたしたが、2番目の単語が耇数圢ではなかったため返されたせんでした。 Twig拡匵機胜を曎新しお修正しおみたしょう。

src / Blogger / BlogBu​​ndle / Twig /拡匵機胜/ BloggerBlogBu​​ndle.php
 <?php // src/Blogger/BlogBundle/Twig/Extensions/BloggerBlogBundle.php namespace Blogger\BlogBundle\Twig\Extensions; class BloggerBlogExtension extends \Twig_Extension { // .. public function createdAgo(\DateTime $dateTime) { // .. if ($delta < 60) { // Seconds $time = $delta; $duration = $time . " second" . (($time === 0 || $time > 1) ? "s" : "") . " ago"; } // .. } // .. }
      
      









単䜓テストを再起動したす。 最初のステヌトメントは正しく衚瀺されたすが、テストは倱敗したす。 次の結論を芋おみたしょう。



 1) Blogger\BlogBundle\Tests\Twig\Extensions\BloggerBlogExtensionTest::testCreatedAgo Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -'1 hour ago' +'60 minutes ago'
      
      







5番目のステヌトメントが倱敗するこずがわかりたす。 テストを芋るず、Twig拡匵が適切に機胜しおいないこずがわかりたす。 1時間前に返されるはずでしたが、代わりに60分前に返されたした。 BloggerBlogExtension Twigのコヌドを芋るず、その理由がわかりたす。 オンにできる時間を比范したす。぀たり、 <の代わりに< =を䜿甚したす。 Twig拡匵機胜を曎新しお修正する

src / Blogger / BlogBu​​ndle / Twig /拡匵機胜/ BloggerBlogBu​​ndle.php
 <?php // src/Blogger/BlogBundle/Twig/Extensions/BloggerBlogBundle.php namespace Blogger\BlogBundle\Twig\Extensions; class BloggerBlogExtension extends \Twig_Extension { // .. public function createdAgo(\DateTime $dateTime) { // .. else if ($delta < 3600) { // Mins $time = floor($delta / 60); $duration = $time . " minute" . (($time > 1) ? "s" : "") . " ago"; } else if ($delta < 86400) { // Hours $time = floor($delta / 3600); $duration = $time . " hour" . (($time > 1) ? "s" : "") . " ago"; } // .. } // .. }
      
      









次のコマンドを䜿甚しお、すべおのテストを再床実行したす。



 $ phpunit -c app
      
      







これにより、すべおのテストが実行され、すべおのテストが成功したこずが瀺されたす。 少数の単䜓テストのみを蚘述したしたが、コヌドを蚘述するずきのテストがどれほど匷力で重芁なものであるかを理解しおください。 テストは、以前の機胜を損なうこずなく、プロゞェクトに将来の機胜を远加するのにも圹立ちたす。 これで、単䜓テストのレビュヌを終了したす。



ヒント



独自の単䜓テストを远加しおみおください。





機胜テスト



ナニットテストをいく぀か䜜成したした。次に、いく぀かのコンポヌネントを䞀緒にテストしたす。 機胜テストの最初のセクションには、生成された応答をテストするためのブラりザヌ芁求のシミュレヌションが含たれたす。



Aboutペヌゞのテスト


たず、AboutペヌゞのPageControllerクラスをテストしたす。 ペヌゞは非垞にシンプルなので、ここから始めるのが良いでしょう。 新しいファむルを䜜成する

src / Blogger / BlogBu​​ndle / Tests / Controller / PageControllerTest.php
 <?php // src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php namespace Blogger\BlogBundle\Tests\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class PageControllerTest extends WebTestCase { public function testAbout() { $client = static::createClient(); $crawler = $client->request('GET', '/about'); $this->assertEquals(1, $crawler->filter('h1:contains("About symblog")')->count()); } }
      
      









コントロヌラのテストはDefaultControllerTestクラスに非垞に䌌おいるこずがわかりたす。 aboutペヌゞをテストしお、生成されたHTML内、぀たりH1タグ内にあるAbout symblog行を確認したす。 PageControllerTestクラスは、ナニットテストの䟋で芋たように、\ PHPUnit_Framework_TestCaseを拡匵したせんが、代わりにWebTestCaseクラスを拡匵したす。 このクラスはSymfony2 FrameworkBundleの䞀郚です。



䞊蚘で説明したように、PHPUnitテストクラスは\ PHPUnit_Framework_TestCaseを拡匵する必芁がありたすが、いく぀かのテストで远加たたは䞀般的な機胜が必芁な堎合は、独自のクラスにカプセル化しおテストクラスを拡匵するず䟿利です。 WebTestCaseはたさにそれを行い、Symfony2で機胜テストを実行するためのいく぀かの䟿利なメ゜ッドを提䟛したす。 vendor / symfony / symfony / src / Symfony / Bundle / FrameworkBundle / Test / WebTestCase.phpにあるWebTestCaseファむルを芋るず、このクラスが実際にはKernelTestCaseクラスの拡匵であるこずがわかりたす。



 // vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php abstract class WebTestCase extends KernelTestCase { // .. }
      
      







WebTestCaseクラスのcreateClientメ゜ッドを芋るず、Symfony2カヌネルのむンスタンスが䜜成されおいるこずがわかりたす。 さらにメ゜ッドを実行するず、createClient匕数の1぀ずしおオヌバヌラむドされない限り環境がテストに蚭定されおいるこずにも気付くでしょう。 これは、前のパヌトで説明したテスト環境です。



テストクラスを芋るず、テストを取埗しお実行するためにcreateClientメ゜ッドが呌び出されおいるこずがわかりたす。 次に、クラむアント偎でrequestメ゜ッドを呌び出しお、ブラりザのURL / aboutでGET HTTPリク゚ストをシミュレヌトしたすブラりザでhttp// localhost8000 / aboutペヌゞにアクセスした堎合もたったく同じです。 芁求は、応答を含むCrawlerオブゞェクトを提䟛したす。 Crawlerクラスは、返されたHTMLを移動できるため、非垞に䟿利です。 Crawlerむンスタンスを䜿甚しお、HTML応答のH1タグにAbout symblogずいう単語が含たれおいるこずを確認したす。 WebTestCaseクラスを拡匵しおも、以前ず同じようにAssertメ゜ッドを䜿甚したすPageControllerTestクラスは\ PHPUnit_Framework_TestCaseクラスの子孫であるこずに泚意しおください。



次のコマンドでPageControllerTestを実行したしょう。 テストを䜜成するずきは、珟圚䜜業しおいるファむルに察しおのみテストを実行するために䜿甚するず䟿利です。



 $ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php
      
      







メッセヌゞOK1぀のテスト、1぀のアサヌションが衚瀺され、1぀のステヌトメントassertEqualsを含む1぀のテストtestAboutが起動されたこずがわかりたす。



About symblog行をContactに倉曎しおから、テストを再床実行しおください。 Contactが芋぀からず、assertEqualsがfalseになるため、テストは倱敗したす。

続行する前に、symblogに぀いおの行を戻したす。

Crawlerむンスタンスを䜿甚するず、HTMLたたはXMLドキュメントを衚瀺できたす぀たり、CrawlerはHTMLたたはXMLを返す応答でのみ機胜したす。 Crawlerを䜿甚しお、filter、first、last、parentなどのメ゜ッドを䜿甚しお、生成された応答を走査できたす。 以前にjQueryを䜿甚したこずがある堎合は、Crawlerクラスに慣れる必芁がありたす。 サポヌトされおいるクロヌラヌの回避策の完党なリストに぀いおは、Symfony2のテストの章を参照しおください。



ホヌムペヌゞ




[About]ペヌゞのテストは簡単でしたが、サむトペヌゞの機胜テストの基本原則を抂説したした。



顧客の創造



ペヌゞリク゚スト



応答チェック



これはプロセスの簡単な抂芁であり、実際には、リンクをクリックする、フォヌムに蚘入しお送信するなど、他の倚くの手順を実行できたす。

ホヌムペヌゞをテストするメ゜ッドを䜜成したしょう。 メむンペヌゞにはroute /経由でアクセスでき、最新のブログ゚ントリを衚瀺する必芁があるこずがわかっおいたす。 新しいtestIndexメ゜ッドをPageControllerTestクラスに远加したす

src / Blogger / BlogBu​​ndle / Tests / Controller / PageControllerTest.php
 // src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php public function testIndex() { $client = static::createClient(); $crawler = $client->request('GET', '/'); // Check there are some blog entries on the page $this->assertTrue($crawler->filter('article.blog')->count() > 0); }
      
      









aboutペヌゞのテストず同じ手順を芋るこずができたす。 テストを実行しお、すべおが正しく機胜しおいるこずを確認したす。



 $ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php
      
      







もう少し先に進みたしょう。 機胜テストの䞀郚には、ナヌザヌがサむトで行うこずを繰り返す機胜が含たれたす。 サむトのペヌゞをナビゲヌトするには、ナヌザヌがリンクをクリックしたす。 このアクションをシミュレヌトしお、タむトルがクリックされたずきに蚘録ペヌゞぞのリンクの正確性を確認したしょう。
PageControllerTestクラスのtestIndexメ゜ッドを曎新する
// src / Blogger / BlogBu​​ndle / Tests / Controller / PageControllerTest.php



パブリック関数testIndex

{

// ...



//最初のリンクを芋぀けおタむトルを取埗し、これが次のペヌゞにロヌドされおいるこずを確認したす

$ blogLink = $ crawler-> filter 'article.blog h2 a'-> first;

$ blogTitle = $ blogLink-> text;

$ crawler = $ client-> click$ blogLink-> link;



// h2にブログタむトルが含たれおいるこずを確認したす

$ this-> assertEquals1、$ crawler-> filter 'h2contains "'。$ blogTitle。 '"'-> count;

}





最初に行うこずは、クロヌラヌを䜿甚しお、投皿タむトルの最初のリンクからテキストを抜出するこずです。 これは、 article.blog h2 a filterを䜿甚しお行われたす。 このフィルタヌは、 article.blog蚘事のH2タグ内のタグを返すために䜿甚されたす。 これをよりよく理解するには、゚ントリヌを衚瀺するためにホヌムペヌゞで䜿甚されるマヌクアップを芋おください。

 <article class="blog"> <div class="date"><time datetime="2016-06-17T14:23:55+03:00">Friday, June 17, 2016</time></div> <header> <h2><a href="/1/a-day-with-symfony2">A day with Symfony2</a></h2> </header> //.. </article>
      
      







article.blog h2の構造は、ホヌムペヌゞのレむアりトのフィルタヌで確認できたす。 たた、マヌクアップに䞀郚があるこずにも気付くでしょう。぀たり、クロヌラヌフィルタヌはコレクションを返したす。 最初のリンクのみが必芁なので、コレクションの最初のメ゜ッドを䜿甚したす。 clickメ゜ッドはリンクオブゞェクトを受け取り、Crawlerむンスタンスで応答を返したす。 Crawlerオブゞェクトが機胜テストの重芁な芁玠であるこずに気付くでしょう。

これで、Crawlerオブゞェクトにブログペヌゞの応答が含たれたす。 リンクが目的のペヌゞにリダむレクトされるこずをテストする必芁がありたす。 前に抜出した$ blogTitle倀を䜿甚しお、応答のタむトルを確認できたす。

テストを実行しお、ホヌムペヌゞず投皿ペヌゞ間のナビゲヌションが正しく機胜するこずを確認したす。



 $ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php
      
      







機胜テスト䞭にサむトのペヌゞをナビゲヌトする方法を理解したので、フォヌムのテストに移りたしょう。



連絡先ペヌゞのテスト




Symblogナヌザヌは、連絡先ペヌゞhttp// localhost8000 / contactのフォヌムに蚘入しお、連絡先リク゚ストを送信できたす。ク゚リが正しく機胜するこずをテストしおみたしょう。最初に、フォヌムが正垞に送信されたずきに䜕が起こるかを決定する必芁がありたすこの堎合、正垞に送信されるずは、゚ラヌのないフォヌムを意味したす。



連絡先ペヌゞに移動したす。



フォヌムにデヌタを入力したす。フォヌムを



送信したす。



レタヌが送信されたこずを



確認したす。送信が成功したこずを確認し




たす。



配眮されたPageControllerTestクラスに新しいtestContactメ゜ッドを远加したす

src / Blogger / BlogBu​​ndle / Tests / Controller / PageControllerTest.php
 // src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php public function testContact() { $client = static::createClient(); $crawler = $client->request('GET', '/contact'); $this->assertEquals(1, $crawler->filter('h1:contains("Contact symblog")')->count()); // Select based on button value, or id or name for buttons $form = $crawler->selectButton('Submit')->form(); $form['contact[name]'] = 'name'; $form['contact[email]'] = 'email@email.com'; $form['contact[subject]'] = 'Subject'; $form['contact[body]'] = 'The comment body must be at least 50 characters long as there is a validation constrain on the Enquiry entity'; $crawler = $client->submit($form); $this->assertEquals(1, $crawler->filter('.blogger-notice:contains("Your contact enquiry was successfully sent. Thank you!")')->count()); }
      
      









url / contactリク゚ストで開始し、ペヌゞに正しいH1ヘッダヌが含たれおいるこずを確認したす。次に、クロヌラヌを䜿甚しお送信ボタンを遞択したす。フォヌムではなくボタンを遞択する理由は、フォヌムに耇数のボタンが含たれおいる堎合があり、それらを互いに独立しおクリックする堎合があるためです。遞択したボタンからフォヌムを取埗できたす。[]配列を䜿甚しおフォヌムの倀を蚭定できたす。最埌に、フォヌムはクラむアントのsubmitメ゜ッドに送信され、フォヌムを送信したす。い぀ものように、Crawlerむンスタンスを取埗したす。クロヌラヌの応答を䜿甚しお、返された応答にフラッシュメッセヌゞが存圚するこずを確認したす。テストを実行しお、すべおが正垞に機胜しおいるこずを確認したす。



 $ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php
      
      







テストは倱敗したした。 次のPHPUnitメッセヌゞを受け取りたす



 1) Blogger\BlogBundle\Tests\Controller\PageControllerTest::testContact Failed asserting that 0 matches expected 1. D:\local\symfony-blog\src\Blogger\BlogBundle\Tests\Controller\PageControllerTest.php:55 FAILURES! Tests: 3, Assertions: 5, Failures: 1.
      
      







結論は、フォヌムが送信された埌の応答でフラッシュメッセヌゞが芋぀からないこずを瀺しおいたす。これは、テスト環境にいるずきにリダむレクトが実行されないために発生したした。 PageControllerクラスでフォヌムが正垞に怜蚌されるず、リダむレクトが発生したす。このリダむレクトは発生したせん。尊重する必芁があるこずを明瀺的に瀺す必芁がありたす。リダむレクトが実行されない理由は、珟圚の応答を最初に確認する必芁がある可胜性があるため、単玔です。これは、埌でメッセヌゞが送信されたかどうかを確認するずきに衚瀺されたす。 PageControllerTestクラスを曎新しお、リダむレクトを蚭定したす。



 // src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php public function testContact() { // .. $crawler = $client->submit($form); // Need to follow redirect $crawler = $client->followRedirect(); $this->assertEquals(1, $crawler->filter('.blogger-notice:contains("Your contact enquiry was successfully sent. Thank you!")')->count()); }
      
      







ここで、PHPUnitテストを実行する堎合、それらに合栌する必芁がありたす。次に、連絡先フォヌムの送信プロセスをチェックする最終段階、ステップ4、メヌルが送信されたこずを確認したす。次の構成が原因で、テスト環境でメヌルが配信されないこずがすでにわかっおいたす。



 # app/config/config_test.yml swiftmailer: disable_delivery: true
      
      







Webプロファむラヌを通じお収集された情報を䜿甚しお、電子メヌルが送信されたこずを確認できたす。ここで、クラむアントをリダむレクトしないこずが重芁です。プロファむラヌの怜蚌は、リダむレクトが発生する前に行う必芁がありたす。そうしないず、プロファむラヌ内の情報が倱われたす。

testContactメ゜ッドを曎新する
 // src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php public function testContact() { // .. $crawler = $client->submit($form); // Check email has been sent if ($profile = $client->getProfile()) { $swiftMailerProfiler = $profile->getCollector('swiftmailer'); // Only 1 message should have been sent $this->assertEquals(1, $swiftMailerProfiler->getMessageCount()); // Get the first message $messages = $swiftMailerProfiler->getMessages(); $message = array_shift($messages); $symblogEmail = $client->getContainer()->getParameter('blogger_blog.emails.contact_email'); // Check message is being sent to correct address $this->assertArrayHasKey($symblogEmail, $message->getTo()); } // Need to follow redirect $crawler = $client->followRedirect(); $this->assertTrue($crawler->filter('.blogger-notice:contains("Your contact enquiry was successfully sent. Thank you!")')->count() > 0); }
      
      









フォヌムを送信した埌、珟圚の環境の構成を䜿甚しおプロファむラヌを無効にできるため、プロファむラヌが䜿甚可胜かどうかを確認したす。



ヒント



テストはテスト環境で実行するのではなく、プロファむラヌなどが利甚できない本番環境で実行する必芁があるこずに泚意しおください。





プロファむラヌを取埗できる堎合は、swiftmailerコレクタヌを取埗するリク゚ストを䜜成したす。swiftmailerコレクタヌは舞台裏で働き、電子メヌルサヌビスの䜿甚方法に関する情報を収集したす。これを䜿甚しお、送信された手玙に関する情報を取埗できたす。

次に、getMessageCountメ゜ッドを䜿甚しお、1぀の電子メヌルが送信されたこずを確認したす。これは、メヌルが送信されたこずを確認するには十分ですが、メヌルが適切な堎所に送信されるこずを確認したせん。

ここでテストを再開し、すべおが正垞に機胜しおいるこずを確認したす。



 $ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/PageControllerTest.php
      
      







远加コメントのテスト


次に、連絡先情報ペヌゞの以前のテストで埗られた知識を䜿甚しお、投皿にコメントを远加するプロセスをテストしたしょう。繰り返したすが、フォヌムが正垞に送信されたずきに䜕が起こるべきかを抂説したす。



ペヌゞの蚘録ぞの移行



するためのフォヌムを蚘入



フォヌム送信



コメントすべおのコメントの最埌に远加されたこずを確認し



、最新のコメントコメントリストの最初のものをチェックし、サむドバヌのブロックを




䞭に新しいファむルを䜜成したす。

src / Blogger / BlogBu​​ndle / Tests / Controller / BlogControllerTest.php
 <?php // src/Blogger/BlogBundle/Tests/Controller/BlogControllerTest.php namespace Blogger\BlogBundle\Tests\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class BlogControllerTest extends WebTestCase { public function testAddBlogComment() { $client = static::createClient(); $crawler = $client->request('GET', '/1/a-day-with-symfony'); $this->assertEquals(1, $crawler->filter('h2:contains("A day with Symfony2")')->count()); // Select based on button value, or id or name for buttons $form = $crawler->selectButton('Submit')->form(); $crawler = $client->submit($form, array( 'blogger_blogbundle_commenttype[user]' => 'name', 'blogger_blogbundle_commenttype[comment]' => 'comment', )); // Need to follow redirect $crawler = $client->followRedirect(); // Check comment is now displaying on page, as the last entry. This ensure comments // are posted in order of oldest to newest $articleCrawler = $crawler->filter('section .previous-comments article')->last(); $this->assertEquals('name', $articleCrawler->filter('header span.highlight')->text()); $this->assertEquals('comment', $articleCrawler->filter('p')->last()->text()); // Check the sidebar to ensure latest comments are display and there is 10 of them $this->assertEquals(10, $crawler->filter('aside.sidebar section')->last() ->filter('article')->count() ); $this->assertEquals('name', $crawler->filter('aside.sidebar section')->last() ->filter('article')->first() ->filter('header span.highlight')->text() ); } }
      
      









コヌドの調査を開始する前に、このファむルのテストを実行しお、すべおが正垞に機胜しおいるこずを確認したす。

 $ phpunit -c app/ src/Blogger/BlogBundle/Tests/Controller/BlogControllerTest.php
      
      







PHPUnitは、1぀のテストが成功したこずを通知する必芁がありたす。testAddBlogCommentのコヌドを芋るず、クラむアントの䜜成、ペヌゞのリク゚スト、およびその怜蚌を確認できたす。次に、コメントの远加フォヌムを受信し、フォヌムを送信したす。フォヌムの倀を入力する方法は、以前のバヌゞョンずは少し異なりたす。今回はsubmitメ゜ッドの2番目のクラむアント匕数を䜿甚しおフォヌム倀を远加したす。



ヒント



オブゞェクト指向のむンタヌフェむスを䜿甚しお、フォヌムフィヌルドの倀を蚭定するこずもできたす。以䞋に䟋を瀺したす。



 // Tick a checkbox $form['show_emal']->tick(); // Select an option or a radio $form['gender']->select('Male');
      
      









フォヌムを送信した埌、応答を確認できるようにリダむレクトに埓う必芁があるクラむアントをリク゚ストしたす。クロヌラヌを再び䜿甚しお、最新のブログコメントを取埗したす。最埌に、サむドバヌの最新のコメントをチェックしお、コメントがリストの最初であるこずを確認したす。



ブログリポゞトリ


機胜テストの最埌の郚分では、Doctrine 2リポゞトリのテストを調べたす。新しいファむルを䜜成する
src / Blogger / BlogBu​​ndle /テスト/リポゞトリ/ BlogRepositoryTest.php
 <?php // src/Blogger/BlogBundle/Tests/Repository/BlogRepositoryTest.php namespace Blogger\BlogBundle\Tests\Repository; use Blogger\BlogBundle\Entity\Repository\BlogRepository; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class BlogRepositoryTest extends WebTestCase { /** * @var \Blogger\BlogBundle\Entity\Repository\BlogRepository */ private $blogRepository; public function setUp() { $kernel = static::createKernel(); $kernel->boot(); $this->blogRepository = $kernel->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('BloggerBlogBundle:Blog'); } public function testGetTags() { $tags = $this->blogRepository->getTags(); $this->assertTrue(count($tags) > 1); $this->assertContains('symblog', $tags); } public function testGetTagWeights() { $tagsWeight = $this->blogRepository->getTagWeights( array('php', 'code', 'code', 'symblog', 'blog') ); $this->assertTrue(count($tagsWeight) > 1); // Test case where count is over max weight of 5 $tagsWeight = $this->blogRepository->getTagWeights( array_fill(0, 10, 'php') ); $this->assertTrue(count($tagsWeight) >= 1); // Test case with multiple counts over max weight of 5 $tagsWeight = $this->blogRepository->getTagWeights( array_merge(array_fill(0, 10, 'php'), array_fill(0, 2, 'html'), array_fill(0, 6, 'js')) ); $this->assertEquals(5, $tagsWeight['php']); $this->assertEquals(3, $tagsWeight['js']); $this->assertEquals(1, $tagsWeight['html']); // Test empty case $tagsWeight = $this->blogRepository->getTagWeights(array()); $this->assertEmpty($tagsWeight); } }
      
      







デヌタベヌスぞの正しい接続を必芁ずするテストを実行したいので、Symfony2 Kernelをダりンロヌドできるため、WebTestCaseを再床拡匵したす。次のコマンドでこのファむルのテストを実行したす。



 $ phpunit -c app/ src/Blogger/BlogBundle/Tests/Repository/BlogRepositoryTest.php
      
      







コヌドカバレッゞ


コヌドカバレッゞにより、テストの実行時にコヌドのどの郚分が実行されるかがわかりたす。これにより、テストでカバヌされおいないコヌド郚分を確認し、それらのテストを䜜成するかどうかを決定できたす。



アプリケヌションのコヌドカバレッゞを衚瀺するには、コン゜ヌルに入力したす



 $ phpunit --coverage-html ./phpunit-report -c app/
      
      







コマンドが機胜するこずを芚えおおいおください、phpでxdebugを有効にする必芁がありたす。

これにより、プロゞェクトルヌトのphpunit-reportフォルダヌにコヌドカバレッゞ分析が出力されたす。ブラりザヌでこのフォルダヌからindex.htmlファむルを開き、分析結果を確認したす。







おわりに





テストでは、いく぀かの重芁な領域を調査したした。ナニットテストず機胜テストの䞡方を調べお、サむトが適切に機胜しおいるこずを確認したした。ブラりザのリク゚ストをシミュレヌトする方法ず、Symfony2 Crawlerクラスを䜿甚しおこれらのリク゚ストのレスポンスを怜蚌する方法を芋たした。



゜ヌスずサポヌト資料



https : //symfony.com/

http://tutorial.symblog.co.uk/

https://phpunit.de/



ポスト台本
プロゞェクトに寄せられた泚意ずコメントに感謝したす。問題や質問がある堎合は、コメントやプラむベヌトメッセヌゞの賌読を解陀し、友達ずしお远加しおください。




パヌト1-Symfony2ずテンプレヌトの構成

パヌト2-連絡先ペヌゞバリデヌタヌ、フォヌム、およびメヌル

パヌト3-Doctrine 2ずデヌタフィクスチャ

パヌト4-Doctrine 2のコメントモデル、リポゞトリ、移行

パヌト5-Twig拡匵、サむドバヌ、および資産





たた、マニュアルが気に入ったら、プロゞェクトリポゞトリにスタヌを付けるか、賌読するこずができたす。ありがずう



All Articles