测试

编辑本页

警告:您正在浏览的文档欧宝体育电话<一个href="//www.oldmanjams.com/releases/3.1">欧宝娱乐app下载地址Symfony 3.1,现已不再维护。

读<一个href="//www.oldmanjams.com/doc/current/testing.html">本页的更新版本用于Sy欧宝娱乐app下载地址mfony 6.2(当前稳定版本)。

测试

每当您编写新的代码行时,您也可能会添加新的错误。为了构建更好、更可靠的应用程序,应该同时使用功能测试和单元测试来测试代码。

PHPUnit测试框架

欧宝娱乐app下载地址Symfony集成了一个名为PHPUnit的独立库,为您提供了一个丰富的测试框架。本章不会涉及PHPUnit本身,但它有自己的优点<一个href="https://phpunit.de/manual/current/en/" class="reference external" rel="external noopener noreferrer" target="_blank">欧宝体育电话

请注意

建议使用最新的稳定PHPUnit版本,<一个href="https://phpunit.de/manual/current/en/installation.html" class="reference external" rel="external noopener noreferrer" target="_blank">安装为PHAR

每个测试——无论是单元测试还是功能测试——都是一个PHP类,应该存在于测试/应用程序的目录。如果您遵循此规则,那么您可以使用以下命令运行应用程序的所有测试:

1
phpunit)

PHPunit由phpunit.xml.dist在Symfony应用程序的根目录下。欧宝娱乐app下载地址

提示

方法可以生成代码覆盖——覆盖- *选项,请参阅使用时显示的帮助信息——帮助获取更多信息。

单元测试

单元测试是针对单个PHP类的测试,也称为单位.如果您想测试应用程序的整体行为,请参阅有关的部分<一个href="//www.oldmanjams.com/doc/3.1/testing.html" class="reference internal">功能测试

编写Symfon欧宝娱乐app下载地址y单元测试与编写标准的PHPUnit单元测试没有什么不同。假设,比如说,你有一个令人难以置信的类调用计算器Util /应用程序包目录:

1 2 3 4 5 6 7 8 9 10
/ / src / AppBundle / Util / Calculator.php名称空间AppBundle跑龙套计算器公共函数添加一个b返回一个+b;}}

要测试这一点,可以创建一个CalculatorTest测试/ AppBundle /跑龙套申请目录:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/ /测试/ AppBundle / Util / CalculatorTest.php名称空间测试AppBundle跑龙套使用AppBundle跑龙套计算器CalculatorTest扩展PHPUnit_Framework_TestCase公共函数testAdd()calc计算器();结果calc->add (30.12);//你的计算器加的数是正确的!->assertequal (42结果);}}

请注意

按照惯例,测试/ AppBundle目录应为单元测试复制包的目录。的类中测试类src / AppBundle / Util /目录,将测试放在测试/ AppBundle / Util /目录中。

就像在您的实际应用程序-自动加载是自动启用通过app / autoload.php文件中默认配置的phpunit.xml.dist文件)。

对给定的文件或目录运行测试也非常简单:

1 2 3 4 5 6 7 8 9 10 11
#运行应用程序的所有测试phpunit)#运行Util目录下的所有测试/ AppBundle / Util phpunit)测试#运行计算器类的测试/ AppBundle / Util / CalculatorTest.php phpunit)测试#运行整个Bundle的所有测试phpunit)测试/ AppBundle /

功能测试

功能测试检查应用程序不同层(从路由到视图)的集成。就PHPUnit而言,它们与单元测试没有什么不同,但它们有一个非常具体的工作流程:

  • 提出请求;
  • 测试响应;
  • 点击链接或提交表单;
  • 测试响应;
  • 清洗并重复。

你的第一个功能测试

功能测试是简单的PHP文件,通常位于测试/ AppBundle /控制器您的包的目录。如果您想测试由您的为PostController类,首先创建一个newPostControllerTest.php扩展特殊类型的文件WebTestCase类。

举个例子,一个测试可以是这样的:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/ /测试/ AppBundle /控制器/ PostControllerTest.php名称空间测试AppBundle控制器使用欧宝娱乐app下载地址FrameworkBundle测试WebTestCasePostControllerTest扩展WebTestCase公共函数testShowPost()客户端静态::createClient ();履带客户端->请求(“得到”' / post / hello world ');->assertGreaterThan (0履带->过滤器(html:包含(“Hello World”)”->count ());}}

提示

要运行功能测试,请使用WebTestCase类引导应用程序的内核。在大多数情况下,这是自动发生的。但是,如果您的内核位于非标准目录中,则需要修改您的内核phpunit.xml.dist文件来设置KERNEL_DIR到内核目录的环境变量:

1 2 3 4 5 6 7
<?XML版本="1.0" charset="utf-8"<phpunit)><php><服务器的名字“KERNEL_DIR”价值“/道路/ /你/ app /”/>php><!——……-->phpunit)>

createClient ()方法返回一个客户端,它就像一个浏览器,你将使用它来抓取你的网站:

1
履带客户端->请求(“得到”' / post / hello world ');

请求()方法(读<一个href="//www.oldmanjams.com/doc/3.1/testing.html" class="reference internal">关于请求方法的更多信息)返回一个<一个href="https://github.com/symfony/symfony/blob/3.1/src/Symfony/Component/DomCrawler/Crawler.php" class="reference external" title="履带" rel="external noopener noreferrer" target="_blank">履带对象,可用于在响应中选择元素、单击链接和提交表单。

提示

履带只有当响应是XML或HTML文档时才有效。要获得原始内容响应,请调用客户端- > getResponse()——> getContent ()

点击一个链接,首先用爬虫选择它,使用XPath表达式或CSS选择器,然后使用客户端单击它。例如:

1 2 3 4 5 6 7 8
链接履带->过滤器(答:包含(“问候”)的//找到所有文本"Greet"的链接->eq (1//选择列表中的第二个链接->链接();//然后点击它履带客户端->点击(链接);

提交表单非常类似:选择一个表单按钮,可选地覆盖一些表单值,并提交相应的表单:

1 2 3 4 5 6 7 8
形式履带->selectButton (“提交”->形式();//设置一些值形式“名字”] =“卢卡斯”形式“form_name(主题)”] =“嘿!”//提交表单履带客户端->提交(形式);

提示

表单还可以处理上传,并包含填充不同类型表单字段的方法(例如。select ()而且蜱虫()).详细信息请参见<一个href="//www.oldmanjams.com/doc/3.1/testing.html" class="reference internal">形式下面的部分。

现在您可以轻松地在应用程序中导航,使用断言来测试它实际上执行了您期望的操作。使用爬虫对DOM进行断言:

1 2
//断言响应匹配给定的CSS选择器。->assertGreaterThan (0履带->过滤器(“标题”->count ());

或者直接测试响应内容,如果你只是想断言内容包含一些文本,或者如果响应不是XML/HTML文档:

1 2 3 4
->assertContains (“Hello World”客户端->getResponse ()->getContent ());

为了让你更快地开始,这里有一个最常见和最有用的测试断言列表:

12 34 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 32 33 34 35 36 37 38 39 40 41 42 43 44 45
使用欧宝娱乐app下载地址组件HttpFoundation响应/ /……//确定至少有一个h2标签//与类"subtitle"->assertGreaterThan (0履带->过滤器(“h2.subtitle”->count ());//断言页面上恰好有4个h2标记->assertCount (4履带->过滤器(“氢气”));//声明"Content-Type"报头为"application/json"->assertTrue (客户端->getResponse ()->->包含(“内容类型”“application / json”),“Content-Type”报头为“application/json”//失败时显示的可选消息);//断言响应内容包含一个字符串->assertContains (“foo”客户端->getResponse ()->getContent ());/ /……或matches a regex->assertRegExp (' / foo (bar) ?/ '客户端->getResponse ()->getContent ());//确认响应状态码为2xx->assertTrue (客户端->getResponse ()->isSuccessful (),'响应状态为2xx');//确认响应状态代码为404->assertTrue (客户端->getResponse ()->isNotFound ());//指定200状态码->assertequal (200//或者Sy欧宝娱乐app下载地址mfony\Component\HttpFoundation\Response::HTTP_OK客户端->getResponse ()->getStatusCode ());//断言响应是一个重定向到/demo/contact->assertTrue (客户端->getResponse ()->isRedirect (“/演示/接触”),'响应是重定向到/demo/contact');/ /……或simply check that the response is a redirect to any URL->assertTrue (客户端->getResponse ()->isRedirect ());

使用测试客户端

测试客户端模拟一个HTTP客户端,就像一个浏览器,并向您的Symfony应用程序发出请求:欧宝娱乐app下载地址

1
履带客户端->请求(“得到”' / post / hello world ');

请求()方法将HTTP方法和URL作为参数,并返回一个履带实例。

提示

硬编码请求url是功能测试的最佳实践。如果测试使用Symfony路由器生成url,它将不会检测到对应用程序url欧宝娱乐app下载地址所做的任何可能影响最终用户的更改。

的完整签名请求()方法是:

1 2 3 4 5 6 7 8 9
请求(方法uri数组参数数组(),数组文件数组(),数组服务器数组(),内容changeHistory真正的

服务器数组是您期望在PHP中通常找到的原始值<一个href="http://php.net/manual/en/reserved.variables.server.php" class="reference external" rel="external noopener noreferrer" target="_blank">$ _SERVERsuperglobal。例如,设置内容类型推荐人而且X-Requested-WithHTTP报头,您将传递以下信息(注意HTTP_非标准标头的前缀):

1 2 3 4 5 6 7 8 9 10 11
客户端->请求(“得到”' / post / hello world '数组(),数组(),数组“CONTENT_TYPE”= >“application / json”“HTTP_REFERER”= >“/ foo / bar”“HTTP_X-Requested-With”= >XMLHttpRequest的,));

使用爬虫程序在响应中查找DOM元素。这些元素可以用来点击链接并提交表单:

1 2 3 4 5
链接履带->selectLink (“去别处……”->链接();履带客户端->点击(链接);形式履带->selectButton (“验证”->形式();履带客户端->提交(形式数组“名字”= >“法”));

click ()而且提交()方法都返回履带对象。这些方法是浏览应用程序的最佳方式,因为它为您处理了很多事情,比如从表单中检测HTTP方法,并为您提供用于上传文件的漂亮API。

提示

您将了解更多关于链接而且形式对象中的<一个href="//www.oldmanjams.com/doc/3.1/testing.html" class="reference internal">履带下面的部分。

请求()方法也可用于直接模拟表单提交或执行更复杂的请求。一些有用的例子:

12 34 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 32 33 34 35 36 37
//直接提交表单(但是使用爬虫更容易!)客户端->请求(“职位”/提交的数组“名字”= >“法”));//在请求体中提交原始JSON字符串客户端->请求(“职位”/提交的数组(),数组(),数组“CONTENT_TYPE”= >“application / json”),”{“名称”:“法”}’);//表单提交和文件上传使用欧宝娱乐app下载地址组件HttpFoundation文件UploadedFile照片UploadedFile (“/道路/ / photo.jpg”“photo.jpg”“图像/ jpeg”123);客户端->请求(“职位”/提交的数组“名字”= >“法”),数组“照片”= >照片));//执行DELETE请求并传递HTTP报头客户端->请求(“删除”' / post / 12数组(),数组(),数组“PHP_AUTH_USER”= >“用户名”“PHP_AUTH_PW”= >“爸爸$ $词”));

最后但并非最不重要的是,你可以强制每个请求在它自己的PHP进程中执行,以避免在同一个脚本中使用多个客户端时产生任何副作用:

1
客户端->使();

爬虫

每次向客户端发出请求时,都会返回一个爬虫实例。它允许您遍历HTML文档,选择节点,查找链接和表单。

形式

可以使用按钮来选择表单,可以使用selectButton ()方法,就像链接一样:

1
buttonCrawlerNode履带->selectButton (“提交”);

请注意

注意,您选择的是表单按钮而不是表单,因为一个表单可以有几个按钮;如果使用遍历API,请记住必须寻找按钮。

selectButton ()方法可以选择按钮标签和提交输入标签。它使用按钮的几个部分来查找它们:

  • 价值属性值;
  • idalt图像的属性值;
  • id的名字的属性值按钮标签。

有了表示按钮的Crawler后,调用形式()方法来获取形式实例,用于包装按钮节点的表单:

1
形式buttonCrawlerNode->形式();

当致电形式()方法,您还可以传递一个覆盖默认值的字段值数组:

1 2 3 4
形式buttonCrawlerNode->形式(数组“名字”= >“法”“my_form(主题)”= >“欧宝娱乐app下载地址Symfony岩石!”));

如果你想为表单模拟一个特定的HTTP方法,将它作为第二个参数传递:

1
形式buttonCrawlerNode->形式(数组(),“删除”);

客户可以提交形式实例:

1
客户端->提交(形式);

属性的第二个参数传递字段值提交()方法:

1 2 3 4
客户端->提交(形式数组“名字”= >“法”“my_form(主题)”= >“欧宝娱乐app下载地址Symfony岩石!”));

对于更复杂的情况,请使用形式实例作为数组单独设置每个字段的值:

1 2 3
//改变一个字段的值形式“名字”] =“法”形式“my_form(主题)”] =“欧宝娱乐app下载地址Symfony岩石!”

还有一个很好的API来根据字段的类型来操作字段的值:

1 2 3 4 5 6 7 8
//选择一个选项或收音机形式“国家”->选择(“法国”);//勾选复选框形式“like_欧宝娱乐app下载地址symfony”->蜱虫();//上传文件形式“照片”->上传(“/道路/ / lucas.jpg”);

提示

如果您有意选择“无效”的选择/单选值,请参见<一个href="//www.oldmanjams.com/doc/3.1/components/dom_crawler.html" class="reference internal">DomCrawler组件

提示

方法可以获得将要提交的值getvalue ()方法。形式对象。返回的单独数组中有上传的文件getfile ().的getPhpValues ()而且getPhpFiles ()方法也会返回提交的值,但是是PHP格式(它转换了带有方括号符号的键)。my_form(主题)- PHP数组)。

向集合中添加和删除表单

如果你使用<一个href="//www.oldmanjams.com/doc/3.1/form/form_collections.html" class="reference internal">收集表格,不能将字段添加到现有表单$form['task[tags][0][name]'] = 'foo';.这将导致一个错误无法到达的字段“…”因为美元的形式只能用于设置现有字段的值。为了添加新的字段,你必须将值添加到原始数据数组:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//获取表单。形式履带->过滤器(“按钮”->形式();//获取原始值。形式->getPhpValues ();//添加字段到原始值。“任务”] [“标签”] [0] [“名字”] =“foo”“任务”] [“标签”] [1] [“名字”] =“酒吧”//提交包含现有值和新值的表单。履带->客户端->请求(形式->getMethod (),形式->getUri (),形式->getPhpFiles ());// 2个标签被添加到集合中。->assertequal (2履带->过滤器(ul。标签> li'->count ());

在哪里任务[标记][0][名称]是用JavaScript创建的字段的名称。

你可以删除一个现有的字段,例如一个标签:

12 3 4 5 6 7 8 9 10 11 12
//获取表单的值形式->getPhpValues ();//删除第一个标签。设置“任务”] [“标签”] [0]);//提交数据。履带客户端->请求(形式->getMethod (),形式->getUri (),形式->getPhpFiles ());//标签已删除。->assertequal (0履带->过滤器(ul。标签> li'->count ());

测试配置

功能测试使用的客户端创建在特殊环境中运行的内核测验环境。因为Symf欧宝娱乐app下载地址ony加载应用程序/配置/ config_test.yml测验环境,您可以调整应用程序的任何设置专门用于测试。

例如,默认情况下,Swift Mailer配置为实际上是在测验环境。你可以看到这个在swiftmailer配置选项:

  • YAML
  • XML
  • PHP
1 2 3 4 5
# app / config / config_test.yml#……swiftmailer:disable_delivery:真正的

您也可以完全使用不同的环境,或重写默认的调试模式(真正的),将它们作为选项传递给createClient ()方法:

1 2 3 4
客户端静态::createClient (数组“环境”= >“my_test_env”“调试”= >));

的第二个参数来传递它们createClient ()

1 2 3 4
客户端静态::createClient (数组(),数组“HTTP_HOST”= >“en.example.com”“HTTP_USER_AGENT”= >“MySuperBrowser / 1.0”));

你也可以在每个请求的基础上覆盖HTTP头:

1 2 3 4
客户端->请求(“得到”' / '数组(),数组(),数组“HTTP_HOST”= >“en.example.com”“HTTP_USER_AGENT”= >“MySuperBrowser / 1.0”));

提示

中的容器中的服务可用于测试客户端测验环境(或任何地方)<一个href="//www.oldmanjams.com/doc/3.1/reference/configuration/framework.html" class="reference internal">framework.test选项已启用)。这意味着如果需要,您可以完全覆盖该服务。

此工作,包括代码示例,是根据<一个rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">创作共用BY-SA 3.0许可证。