brightmarch / testing-bundle
Symfony 扩展包,帮助进行功能测试和单元测试。
Requires
- php: >=5.4.0
README
这个 Symfony 扩展包使得编写功能测试变得简单,无需头痛,也不需要任何额外的库。该扩展包允许你轻松创建一个客户端来执行针对应用的请求,并访问 Symfony 容器来检索服务。此外,你可以创建认证客户端,以避免在访问应用中认证部分时需要通过登录页面。
使用此扩展包,设置测试数据也非常简单。你不再需要编写单独的类来填充数据库测试数据 - 只需在 YAML 中定义它们,扩展包就会为你处理填充和持久化!
安装
首先,更新你的 composer.json
文件,添加库名称。
{ "require-dev": { "brightmarch/testing-bundle": "2.0.0" } }
使用 Composer 安装扩展包。
composer update --dev brightmarch/testing-bundle
将扩展包类添加到你的 app/AppKernel.php
文件中。
public function registerBundles() { // ... if (in_array($this->getEnvironment(), array('dev', 'test'))) { // ... $bundles[] = new Brightmarch\TestingBundle\BrightmarchTestingBundle(); } return $bundles; }
使用方法
使用扩展包非常简单。它包含一个类 Brightmarch\TestingBundle\TestCase
,你的功能测试套件可以扩展它。
示例测试套件
<?php namespace My\AppBundle\Tests\Controller; use Brightmarch\TestingBundle\TestCase; class AdminControllerTest extends TestCase { public function testAdminRequiresAuthentication() { $client = $this->getClient(); $client->request('GET', $this->getUrl('my_app_admin_index')); $this->assertContains('Sign In', $client->getCrawler()->text()); } public function testAdmin() { $admin = $this->get('doctrine') ->getManager('app') ->getRepository('MyAppBundle:UserAccount') ->findOneByEmail('admin@myapp.com'); // The firewall is named 'admin'. $client = $this->authenticate($admin, 'admin'); $client->request('GET', $this->getUrl('my_example_app_admin_panel')); $this->assertContains('Welcome back, Admin', $client->getCrawler()->text()); } public function testStatelessApi() { $user = $this->getFixture('api_user', 'app'); $client = $this->authenticateStateless($user); $client->request('GET', $this->getUrl('my_example_app_api')); // Test the JSON response for example. } }
容器
使用 getContainer()
方法访问容器非常简单。该方法不接受任何参数,并返回一个设置了以下参数的 Symfony\Component\DependencyInjection\Container
对象:
- 环境:测试
- 调试:开启
你还可以使用 get()
方法从容器中获取任何服务。该方法接受一个参数:你想要检索的服务名称。
客户端
你可以使用 getClient()
方法构建一个 HTTP 客户端。它接受一个可选的数组参数,你可以设置额外的服务器参数。
array $server=[]
认证
当不断需要作为用户登录来执行测试时,测试认证功能会变得很麻烦。authenticate()
方法通过模拟完整的认证过程使这变得简单。该方法接受两个参数,一个是实现 Symfony\Component\Security\Core\User\UserInterface
接口的用户实体,以及你想要认证的来自 app/config/security.yml
文件的防火墙名称。
Symfony\Component\Security\Core\User\UserInterface $user
string $firewall
请注意,authenticate()
方法返回你应该用于所有未来与你的应用交互的客户端。你不需要首先调用 getClient()
。
此扩展包的 1.2.0
版本引入了一个名为 authenticateStateless()
的方法,允许你针对无状态的防火墙进行认证。这对于 API 测试很有用,其中你的 API 是无状态的,并且每个请求都需要授权。像 authenticate()
方法一样,此方法返回一个你可以用来与你的 API 交互的客户端。因为你通过应用的 URL 与应用交互,所以不需要提供防火墙来认证。
数据库交互
从版本 1.3.0
开始,TestCase
类要求你必须使用一个命名的实体管理器。所有安装和检索测试数据的实体管理器访问都必须通过命名的管理器完成。
因为 get()
方法是公开的,用于检索任何服务,你可以这样访问 Doctrine 实体管理器:
$_em = $this->get('doctrine') ->getManager('app');
测试数据
从版本 2.0.0 开始,此扩展包可以自动处理填充和安装你的数据库测试数据。你不需要依赖于 Doctrine Fixtures 扩展包,而是可以在 YAML 中编写你的测试数据,并由扩展包自动持久化。
TestCase
类有一个名为 installDataFixtures()
的受保护方法,它将使用 Doctrine 在关系型数据库中安装数据集(MongoDB 不受支持)。它接受两个参数,一个是必需的,另一个是可选的。
string $managerName
boolean $append=false
$managerName
参数是要运行的实体管理器的实体管理器。$append
参数确定实体是追加到数据库还是先清除。默认情况下,所有数据都会先清除。
建议您在父级的 setUp()
方法中调用 installDataFixtures()
方法,以便在每次测试执行之前安装数据集。这会减慢您的测试速度,但可以确保它们在隔离的环境中执行。
首先,在您的应用程序的 app/config/
目录中创建一个名为 fixtures.yml
的文件。您需要创建两个级别的嵌套来定义您的数据集。
parameters: fixtures:
您将所有数据集信息放在 fixtures
节点下。例如,如果您有一个表示应用程序中用户的实体,您可以创建一个名为 admin_user
的数据集,如下面的 fixtures.yml
文件所示:
parameters: fixtures: admin_user: _entity: MyCompany\AppBundle\Entity\User username: admin_user password: my_password full_name: The Boss age: 42 gender: Male
当调用 installDataFixtures()
时,它将构建一个新的 User
对象,通过调用 setUsername()
、setPassword()
、setFullName()
、setAge()
和 setGender()
来填充它。然后将其持久化到数据库中。该数据集将存储在一个名为 admin_user
的内部数组中。
您的数据集中的字段名可以使用 snake_case
或 camelCase
。例如,full_name
和 fullName
都将用于调用 setFullName()
。
您可以通过使用接受两个必需参数的 getFixture()
方法在任何测试中检索该数据集
string $fixture
string $managerName
$fixture
参数是要检索的数据集的名称(例如 admin_user
),而 $managerName
参数是跟踪该数据集的实体管理器的名称。
交叉引用的实体也可以在 fixtures.yml
文件中配置。例如,在创建 admin_user
后,如果您需要创建一个引用 admin_user
的 product
数据集,您可以通过在值前加波浪线来实现。
parameters: fixtures: admin_user: _entity: MyCompany\AppBundle\Entity\User username: admin_user password: my_password full_name: The Boss age: 42 gender: Male product: _entity: MyCompany\AppBundle\Entity\Product create_user: ~admin_user name: My Awesome Gadget price: 4299
如果您将字段配置为 date
或 datetime
类型,Doctrine 预期的是一个 DateTime
对象。如果您有一个名为 ordered_at
的字段,其值为 2015-08-01 15:36:45
,则插入将失败,因为 Doctrine 预期它应该是一个对象。
为了解决这个问题,如果您的数据集中的任何值可以用上述格式解析,它将自动转换为 DateTime
对象。也就是说,如果 date_create_from_forat('Y-m-d H:i:s', $value)
返回一个 DateTime
对象,它将用于实体中的该字段。
由于数据集将按照它们在文件中定义的顺序构建,因此 installDataFixtures()
方法将知道在 Product
类上调用 setCreateUser()
,使用的是 admin_user
实例的 User
对象。
最后,实体是按相反的顺序清除的。在上面的例子中,首先清除 product
,然后是 admin_user
。
URL
如果您需要从一个路由(这是一个好习惯,因为它允许您的 URL 改变,而路由保持不变)生成 URL,您可以使用 getUrl()
方法。它接受三个参数:
string $route
array $parameters=[]
boolean $absolute=false
许可
The MIT License (MIT)
版权 (c) 2013-2015 Vic Cherubini, Bright March, LLC