第17步:测试

5.2版本
保持 不明意

测试

当我们开始向应用程序添加越来越多的功能时,它可能是谈论测试的正确时间。

有趣的事实:在本章中写下测试时,我发现了一个错误。

ob娱乐下载Symfony依赖于单位测试的PHPUnit。让我们安装它:

1
$ ob娱乐下载symfony composer req phpunit --dev

写作单元测试

垃圾录是我们要编写测试的第一堂课。生成单元测试:

1
$ ob娱乐下载symfony控制台使:单元测试SpamCheckerTest

测试SpamChecker是一个挑战,因为我们当然不想触及Akismet API。我们要嘲笑API。

让我们写一个第一次测试,因为API返回错误:

patch_file
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
--- a / tests / spamcheckertest.php+++ b / tests / spamcheckertest.php@@ -2,12 + 2,26 @@命名空间app \ tests;+使用App \实体\评论;+使用App \ SpamChecker;使用PHPUnit) \ Framework \ TestCase;+使用Syob娱乐下载mfony \ \ HttpClient \ MockHttpClient组件;+使用Syob娱乐下载mfony \组件\ HttpClient \ \ MockResponse反应;+使用Syob娱乐下载mfony \ \ HttpClient \ ResponseInterface合同;类SpamCheckerTest扩展TestCase {- 公共功能testsomething()+公共函数testspamscorewithinvalidrequest()-  $ this-> ssserttrue(true);+ $comment = new comment ();+ $评论- > setCreatedAtValue ();+ $context = [];++ $client = new MockHttpClient([new MockResponse('invalid', ['response_headers' => ['x-akismet-debug-help: invalid key']])]);+ $ checker = new spamchecker($ client,'abcde');++ $ this - > expectException (\ RuntimeException::类);+ $以下 - > HeakeExceptionMessage('无法检查垃圾邮件:无效(无效键)。');+ $ checker-> getspamscore($评论,$ context);} }

mockhttpclient.类可以模拟任何HTTP服务器。它取一个数组MockResponse包含预期身体和响应标题的实例。

然后,我们称之为getspamscore()方法,并检查是否通过expectException ()phpUnit方法。

运行测试以检查它们是否通过:

1
$ ob娱乐下载symfony php bin / phpunit

让我们为快乐路径添加测试:

patch_file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 21 22 23 23 22 32 29 29 30 31 32 32 34 35
--- a / tests / spamcheckertest.php+++ b / tests / spamcheckertest.php@@ -24,4 +24,32 @@类SpamCheckerTest扩展TestCase$以下 - > HeakeExceptionMessage('无法检查垃圾邮件:无效(无效键)。');$ checker-> getspamscore($评论,$ context);}++ / **+ * @dataprovider getcomments+ * /+公共函数testSpamScore(int $expectedScore, ResponseInterface $response, Comment $ Comment, array $context)+ {+ $ client = new mockhttpclient([$响应]);+ $ checker = new spamchecker($ client,'abcde');++ $score = $checker->getSpamScore($comment, $context);+ $ this - > assertSame (expectedScore美元,美元的分数);+}+public function getComments():可迭代的+ {+ $comment = new comment ();+ $评论- > setCreatedAtValue ();+ $context = [];++ $ response = new mockresponse('',['response_headers'=> ['x-akismet-pro-tip:discard']);+收益率'blatant_spam'=> [2,$响应,$ comment,$ context];++ $response = new MockResponse('true');+产量'垃圾邮件'=> [1,$响应,$评论,$ context];++ $response = new MockResponse('false');+ yield ` ham ` => [0, $response, $comment, $context];+}

PHPUnit数据提供程序允许我们在多个测试用例中重用相同的测试逻辑。

编写控制器功能测试

测试控制器与测试“常规”PHP类有一点不同,因为我们希望在HTTP请求的上下文中运行它们。

为Conference控制器创建一个功能测试:

测试/控制器/ conferenceControllert.php
12 3 4 5 6 7 8 9 10 11 12 13 14 15
名称空间应用\ \测试控制器ob娱乐下载Symfony \包\ FrameworkBundle \ \ WebTestCase测试ConferenceControllertest.延伸WebTestCase.公共功能testIndex()美元的客户静态::createClient();美元的客户- >请求'得到'' / ');这个美元- >assertrecesteSiseucesfess();这个美元- >assertselectortextcontains.“氢气”给你反馈的);

使用ob娱乐下载Symfony \包\ FrameworkBundle \ \ WebTestCase测试而不是PHPUnit) \ \ TestCase的框架作为测试的基类为功能测试提供了一个很好的抽象。

美元的客户变量模拟浏览器。它不允许将HTTP调用用于服务器,而不是直接调用Symfony应用程序。ob娱乐下载此策略具有多种优势:它比客户端和服务器之间的往返更快,但它还允许测试在每个HTTP请求之后对服务的状态进行核解。

第一个测试检查主页是否返回200 HTTP响应。

断言如assertrecesteSiseucesfess是添加在PHPUnit之上的,以简化您的工作。Symfony定义了许多这样的断言。ob娱乐下载

提示

我们已经使用过/而不是通过路由器生成URL。这样做是有目的的,因为测试最终用户url是我们想要测试的一部分。如果你改变了路径,测试将中断,作为一个很好的提醒,你可能应该重定向旧的URL到新的一个,以更好地与搜索引擎和网站链接回你的网站。

请注意

我们可以通过Maker Bundle生成测试:

1
$ ob娱乐下载Symfony控制台:功能测试控制器\\ConferenceController

配置测试环境

默认情况下,PHPUnit测试在运行中测试ob娱乐下载Symfony环境定义在PHPUnit配置文件:

phpunit.xml.dist
1 2 3 4 5 6 7 8 9
php > <名称=“error_reporting”价值=“1”/><服务器名称=“app_env”价值=“测试”力=“真的”/><服务器名称=“SHELL_VERBOSITY”价值=“1”/><服务器名称=“ob娱乐下载SYMFONY_PHPUNIT_REMOVE”价值=""/><服务器名称=“ob娱乐下载SYMFONY_PHPUNIT_VERSION”价值=“8.5”/>

为了使测试有效,我们必须设置AKISMET_KEY对于这个秘密测试环境:

1
app_env.测试ob娱乐下载Symfony控制台秘密:设置Akismet_Key

请注意

如前一章所示,app_env = test.意味着app_env.为命令的上下文设置环境变量。在窗户上,使用——env =测试而不是:ob娱乐下载安慰秘密:设置AKISMET_KEY——env =测试

使用测试数据库

正如我们已经看到的,Symfony CLI自动公开ob娱乐下载database_url.环境变量。当app_env.测试,就像运行PHPUnit时设置的那样,它将更改数据库名称主要的main_test.这样测试都有自己的数据库。这非常重要,因为我们需要一些稳定的数据来运行我们的测试,我们当然不想覆盖我们存储在开发数据库中的内容。

在能够运行测试之前,我们需要“初始化”测试数据库(创建数据库并迁移它):

1 2
app_env.测试ob娱乐下载Symfony控制台原则:数据库:创建$app_env.测试ob娱乐下载Symfony控制台原则:迁移:迁移-n

如果您现在运行测试,PHPUnit不会再与您的开发数据库交互。只需运行新测试,将路径传递给他们的类路径:

1
app_env.测试ob娱乐下载Symfony PHP BIN / PHPUNIT测试/控制器/ CONFERENCECONTROLLEST.php

注意,我们正在设置app_env.即使在运行PHPUnit以让Symfony CLI将数据库名称设置为ob娱乐下载main_test.

提示

当测试失败时,识别响应对象可能很有用。通过客户端- > getResponse ()回声它看它看起来像什么。

定义设备

为了能够测试评论列表,分页和表单提交,我们需要使用一些数据填充数据库。我们希望测试在测试运行之间具有相同的数据,以使测试通过。夹具正是我们所需要的。

安装Doctrine fixture包:

1
$ ob娱乐下载symfony composer req orm-fixtures——dev

一个新的src / datafixtures /使用示例类安装在安装期间创建目录,准备自定义。立即添加两个会议和一个评论:

patch_file
1 2 3 4 5 6 7 8 9 10 11 12 32 32 32 32 32 32 32 32 32 32 32 32 32 37 37 37 32 37 37 32
--- a / src / datafixtures / appfixtures.php+ + + b / src / DataFixtures / AppFixtures.php@@ -2,6 +2,8 @@名称空间的应用程序\ DataFixtures;+使用App \实体\评论;+使用app \ entity \会议;使用原则\包\ FixturesBundle \夹具;使用原则\ \ ObjectManager持久性;@@ -9,8 +11,24 @@类Appfixtures延伸夹具{公共功能加载(ObjectManager $ Manager){- // $product = new product ();-  // $ Manager->持久性($产品);+ $amsterdam = new Conference();+ $阿姆斯特丹- > setCity(阿姆斯特丹);+ $阿姆斯特丹- > setYear (' 2019 ');+ $ amsterdam-> setisinternational(true);+ $ Manager-> Persist($ Amsterdam);++ $paris = new Conference();+ $巴黎 - > setcity('巴黎');+ $巴黎- > setYear (' 2020 ');+ $巴黎 - > setisinternational(false);+ $经理- >保存(巴黎);++ $评论1 =新评论();+ $评论1-> setConference($ Amsterdam);+ $ comment1 - > setAuthor(“法”);+ $ comment1 - > setEmail ('(电子邮件保护)');+ $评论1-> Setext('这是一个很棒的会议。);+ $经理- >保存($ comment1);经理- >冲洗();}

当我们加载灯具时,所有数据都将被删除;包括管理员用户。为避免这种情况,让我们在夹具中添加管理员用户:

1 2 3 4 5 6 7 8 9 10 11 12 32 32 32 32 32 32 32 32 32 32 32 32 32 37 37 37 32 37 37 32
--- a / src / datafixtures / appfixtures.php+ + + b / src / DataFixtures / AppFixtures.php@@ -2,13 +2,22 @@名称空间的应用程序\ DataFixtures;+使用App \实体\管理;使用App \实体\评论;使用App \实体\会议;使用原则\包\ FixturesBundle \夹具;使用原则\ \ ObjectManager持久性;+使用Syob娱乐下载mfony核心组件\ \安全\ \编码器\ EncoderFactoryInterface;类AppFixtures扩展夹具{+私人encoderFactory美元;++ public function __construct(EncoderFactoryInterface $encoderFactory)+ {+ $this->encoderFactory = $encoderFactory;+}+public function load(ObjectManager $manager) {$amsterdam = new Conference();@@ -30,6 +39,12 @@类Appfixtures延伸夹具$comment1->setText('这是一个伟大的会议');经理- >保存($ comment1);+ $ admin = new admin();+ $管理- > setRoles ([' ROLE_ADMIN ']);+ $ admin-> setusername('admin');+ $ admin-> setpassword($ this-> encoderfactory-> getencoder(admin :: class) - > encocepassword('admin',null));+ $经理- >保存(管理);+经理- >冲洗();} }

提示

如果您不记得给定任务需要哪种服务,请使用调试:autowiring.有一些关键字:

1
$ ob娱乐下载symfony控制台调试:自动控制编码器

装载夹具

加载固定装置测试环境/数据库:

1
app_env.测试ob娱乐下载symfony控制台学说:夹具:负载

在功能测试中爬网网站

正如我们所看到的,测试中使用的HTTP客户端模拟了一个浏览器,所以我们可以像使用一个无头浏览器一样在网站中导航。

添加一个新的测试,从主页点击会议页面:

patch_file
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
——/ /控制器/ ConferenceControllerTest.php测试+++ b / tests / controller / conferenceControllert.php@@ -14,4 +14,19 @@ class ConferenceControllerTest扩展了WebTestCase$ this - > assertResponseIsSuccessful ();$this->assertSelectorTextContains('h2', '给你的反馈');}++公共函数testconfernerdpage()+ {+ $ client = static :: createClient();+ $ crawler = $ client->请求('get','/');++ $ this - > assertCount(2,履带- >过滤器(h4));++客户端- > clickLink(“视图”);++ $ this - > assertPageTitleContains(阿姆斯特丹);+ $ this - > assertResponseIsSuccessful ();+ $this->assertSelectorTextContains('h2', 'Amsterdam 2019');+ $以下 - > assertselectorexists('div:包含(“有1条评论”)');+}

让我们用通俗易懂的语言来描述一下这次测试:

  • 喜欢第一次测试,我们去主页;
  • 要求()方法返回A.爬行物有助于在页面上查找元素的实例(如链接,表单或任何您可以与CSS选择器或XPath达到的内容);
  • 由于CSS选择器,我们断言我们在主页上列出了两个会议;
  • 然后,点击“查看”链接(因为它一次不能单击多个链接,Symfony会自动选择它发现的第一个);ob娱乐下载
  • 我们断言页面标题,响应和页面< h2 >确保我们在正确的页面(我们也可以检查匹配的路线);
  • 最后,我们断言页面上有1条评论。div:包含()不是一个有效的CSS选择器,但Symfony有一些不错的补充,从job娱乐下载Query借来。

而不是点击文本(即视图),我们也可以通过CSS选择器来选择链接:

1
美元的客户- >点击$履带- >过滤器'h4 + p a'- >链接());

检查新测试是否为绿色:

1
app_env.测试ob娱乐下载Symfony PHP BIN / PHPUNIT测试/控制器/ CONFERENCECONTROLLEST.php

在功能测试中提交表单

你想到下一个级别吗?尝试通过在测试中使用会议上的照片添加新注释。那似乎雄心勃勃,不是吗?看看所需的代码:不比我们已经写的更复杂:

patch_file
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
——/ /控制器/ ConferenceControllerTest.php测试+++ b / tests / controller / conferenceControllert.php@@ -29,4 +29,19 @@类ConferenceControllertest扩展了WebTestCase$以下 - > AssertselectortContains('H2','Amsterdam 2019');$以下 - > assertselectorexists('div:包含(“有1条评论”)');}++公共功能testCommentsubmission()+ {+ $ client = static :: createClient();+ $客户 - >请求('get','/会议/ Amsterdam-2019');+ $客户 - > subsform('提交',[+ 'comment_form[author]' => 'Fabien',+ 'comment_form[text]' => '一些来自自动功能测试的反馈',+ 'comment_form[email]' => '(电子邮件保护)',+ 'comment_form[photo]' => dirname(__DIR__, 2).'/public/images/under-construction.gif',+]);+ $ this - > assertResponseRedirects ();+客户端- > followRedirect ();+ $以下 - > assertselectorexists('div:包含(“有2条评论”)');+}

通过。提交表单submitForm (),通过浏览器DevTools或通过Symfony Profiler表单面板查找输入名称。ob娱乐下载注意巧妙的施工形象的重复使用!

再次运行测试以检查一切是绿色的:

1
app_env.测试ob娱乐下载Symfony PHP BIN / PHPUNIT测试/控制器/ CONFERENCECONTROLLEST.php

如果希望在浏览器中检查结果,请停止Web服务器并重新运行测试环境:

1 2
$ ob娱乐下载symfony server:stop $app_env.测试ob娱乐下载symfony服务器:start -d

重新加载灯具

如果第二次运行测试,则应失败。由于现在在数据库中有更多的评论,因此检查评论数量的断言是破坏的。我们需要通过在每个运行之前重新加载夹具来重置每个运行之间的数据库的状态:

1 2
app_env.测试ob娱乐下载Symfony控制台学说:灯具:加载$app_env.测试ob娱乐下载Symfony PHP BIN / PHPUNIT测试/控制器/ CONFERENCECONTROLLEST.php

使用Makefile实现工作流自动化

为了运行测试,必须记住一系列命令是很烦人的。这至少应该被记录下来。但是文档欧宝官网下载app应该是最后的手段。相反,将日常活动自动化怎么样?这将作为文档,帮助其他开发人员发现,并使欧宝官网下载app开发人员的生活更容易、更快。

用一个makefile.是一种自动化命令的方法:

makefile.
1 2 3 4 5 6 7 8 9 10
贝壳:=/ bin / bash测试出口app_env.测试测试ob娱乐下载Symfony控制台原则:数据库:drop——force||真的ob娱乐下载Symfony控制台原则:数据库:创建Symfony控制台原则:迁移:迁移-n Symfony控制台原则:fixture:加载-n Symfony PHP bin/phpunit(电子邮件保护).PHONY测试

警告

在Makefile规则中,缩进必须由一个制表符而不是空格组成。

注意-N旗帜上的教条命令;它是Symfony命令上的一个全局标志,使它们ob娱乐下载不具有交互性。

无论何时要运行测试,请使用制作测试

1
美元做测试

每次测试后重置数据库

在每个测试运行后重置数据库很好,但具有真正独立的测试更好。我们不希望一次测试依赖以前的测试。更改测试的顺序不应改变结果。正如我们现在要弄清楚的那样,这就是目前的情况。

移动testconfernerpage.试验到TestCommentsubmission.一:

patch_file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 2 21 22 23 32 32 29 32 32 32 32 32 32 40 42 42 44 44 44
——/ /控制器/ ConferenceControllerTest.php测试+++ b / tests / controller / conferenceControllert.php@@ -15,21 +15,6 @@ class ConferenceControllerTest扩展了WebTestCase$this->assertSelectorTextContains('h2', '给你的反馈');}-公共函数testConferencePage()-  {- $client = static::createClient();- $crawler = $client->request('GET', '/');-- $ this - > assertCount(2,履带- >过滤器(h4));--  $ client-> clicklink('查看');-- $ this - > assertPageTitleContains(阿姆斯特丹);-  $ this-> assertresponseSiseuccessful();-  $以下 - > AssertselectortextContains('H2','Amsterdam 2019');-  $以下 - > assertselectorexists('div:包含(“有1条评论”)');- }-public function testCommentSubmission() {$client = static::createClient();@@ -44,4 +29,19 @@类ConferenceControllertest扩展了WebTestCase$客户 - > lowerredirect();$以下 - > assertselectorexists('div:包含(“有2条评论”)');}++公共函数testconfernerdpage()+ {+ $ client = static :: createClient();+ $ crawler = $ client->请求('get','/');++ $ this - > assertCount(2,履带- >过滤器(h4));++客户端- > clickLink(“视图”);++ $ this - > assertPageTitleContains(阿姆斯特丹);+ $ this - > assertResponseIsSuccessful ();+ $this->assertSelectorTextContains('h2', 'Amsterdam 2019');+ $以下 - > assertselectorexists('div:包含(“有1条评论”)');+}

测试现在失败了。

要在测试之间重置数据库,请安装DoctrineTestBundle:

1
$ ob娱乐下载symfony作曲家要求“dama / doctrine-test-bundle: ^ 6”——开发

您需要确认配方的执行(因为它不是“正式”支持的捆绑包):

1 2 3 4 5 6 7 8 9 10 11
ob娱乐下载Symfony操作:1 recipe (d7f110145ba9f62430d1ad64d57ab069) - WARNING dama/doctri -test-bundle (>=4.0): From github.com/symfony/recipes-contrib:master欧宝体育平台怎么样你想要执行这个食谱吗?ob娱乐下载[y] Yes [n] No [a] Yes for all packages, only for the current installation session [p] Yes, never ask again for this project(默认为n): p

启用PHPUnit监听器:

patch_file
12 3 4 5 6 7 8 9 10 11 12 13
——/ phpunit.xml.dist+ + + b / phpunit.xml.dist@@ -27,6 +27,10 @@> < /白名单> < /过滤器+ <扩展>+ <扩展级别=“dama \ doctrinetestbundle \ phpunit \ phpunitextension”/>+ +<侦听器> <侦听器类=“symfony \ bridgeob娱乐下载 \ phpunit \ symfonytestslistener”/> 

和完成。在测试中所做的任何更改现在都会在每个测试结束时自动回滚。

测试应该再次成为绿色:

1
美元做测试

使用真实浏览器进行功能测试

功能测试使用一个特殊的浏览器,直接调用Symfony层。ob娱乐下载但你也可以使用真正的浏览器和真正的HTTP层,感谢Symfony Panther:ob娱乐下载

1
$ ob娱乐下载symfony作曲家要求黑豹-开发

然后,您可以编写测试,使用真正的谷歌Chrome浏览器与以下更改:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 17 18 19
——/ /控制器/ ConferenceControllerTest.php测试+++ b / tests / controller / conferenceControllert.php@@ -2,13 +2,13 @@命名空间app \ tests \ controller;- 使用sob娱乐下载ymfony \ bundle \ frameworkbundle \ test \ webtestcase;+使用Syob娱乐下载mfony \ \豹\ PantherTestCase组件;-class ConferenceControllerTest扩展了WebTestCase+类ConferenceControllert最延伸豹子public function testIndex() {- $client = static::createClient();+ $client = static::createPantherClient(['external_base_uri' => $_SERVER['ob娱乐下载SYMFONY_PROJECT_DEFAULT_ROUTE_URL']); / /创建客户端客户端- >请求(‘得到’,‘/’);$ this - > assertResponseIsSuccessful ();

ob娱乐下载SYMFONY_PROJECT_DEFAULT_ROUTE_URL环境变量包含本地Web服务器的URL。

用Blackfire运行黑匣子功能测试

运行功能测试的另一种方法是使用黑焰的球员.除了您可以处理功能测试的情况下,它还可以执行性能测试。

请参阅“性能”步骤了解更多信息。


这个工作,包括代码示例,是根据Creative Commons By-NC-SA 4.0许可证。