시험
추가 코드 줄을 작성할 때마다 잠재적인 새로운 버그가 추가됩니다. 더 좋고 더 안정적인 프로그램을 구축하려면 코드에 기능 테스트와 단위 테스트를 사용해야 합니다.
PHPUnit 테스트 프레임워크 ¶
Symfony는 PHPUnit이라는 독립적인 클래스 라이브러리를 통합하여 풍부한 테스트 프레임워크를 제공합니다. 이 장에서는 PHPUnit 자체를 다루지는 않지만 PHPUnit 자체의 훌륭한 문서가 있습니다.
최신 안정 버전의 PHPUnit을 사용하고 PHAR을 설치하는 것이 좋습니다.
단위 테스트이든 기능 테스트이든 모든 테스트는 번들의 Tests/
하위 디렉터리에 저장된 PHP 클래스입니다. 이 원칙을 따르면 모든 프로그램 수준 테스트를 실행할 때 다음 명령을 실행하면 됩니다.
PHPunit은 Symfony 루트 디렉터리의 phpunit.xml.dist
파일을 통해 구성됩니다. phpunit.xml.dist
文件进行配置。
代码覆盖(code coverage)可以通过 —coverage-*
选项来生成。要查看帮助信息,可使用 —help
来显示更多内容。
单元测试 ¶
单元测试是针对单一PHP类的测试,这个类也被称为“单元(unit)”。如果你需要测试你的应用程序层级的整体行为,参考[功能测试] (#catalog2)(Functional Tests)。
编写Symfony单元测试和编写标准的PHPUnit单元测试并无不同。假设,你有一个极其简单的类,类名是 Calculator
,位于app bundle的 Util/
目录下:
1
为了测试它,创建一个 CalculatorTest
文件到你的bundle的 tests/AppBundle/Util
目录下:
$ phpunit
根据约定, Tests/AppBundle
目录应该复制你的bundle下的单元测试文件所在的目录。因此,如果你要测试的类位于 src/AppBundle/Util
目录下,那么就把测试代码放在 tests/AppBundle/Util/
—coverage-* code> 옵션을 전달할 수 있습니다. 생성합니다. 도움말 정보를 보려면 —help
를 사용하여 더 많은 콘텐츠를 표시하세요.
단위 테스트 ¶
#🎜🎜#Unit 이 테스트는 "유닛"이라고도 하는 단일 PHP 클래스에 대한 테스트입니다. 애플리케이션 계층의 전체 동작을 테스트해야 하는 경우 기능 테스트(#catalog2)를 참조하세요. #🎜🎜##🎜🎜#Symfony 단위 테스트 작성은 표준 PHPUnit 단위 테스트 작성과 다르지 않습니다. 앱 번들의Util/
디렉터리에 Calculator
라는 매우 간단한 클래스가 있다고 가정해 보겠습니다. #🎜🎜#// src/AppBundle/Util/Calculator.phpnamespace AppBundle\Util; class Calculator{ public function add($a, $b) { return $a + $b; }}#🎜🎜#테스트하려면 다음을 생성하세요. 번들의
tests/AppBundle/Util
디렉토리에 있는 CalculatorTest
파일:#🎜🎜#
// tests/AppBundle/Util/CalculatorTest.phpnamespace Tests\AppBundle\Util; use AppBundle\Util\Calculator; class CalculatorTest extends \PHPUnit_Framework_TestCase{ public function testAdd() { $calc = new Calculator(); $result = $calc->add(30, 12); // assert that your calculator added the numbers correctly! $this->assertEquals(42, $result); }}#🎜🎜#
# 🎜🎜#
Tests/AppBundle
디렉터리는 번들 아래의 단위 테스트 파일이 있는 디렉터리에 복사되어야 합니다. 따라서 테스트하려는 클래스가 src/AppBundle/Util
디렉터리에 있으면 테스트 코드를 tests/AppBundle/Util/
디렉터리에 배치하세요. #🎜🎜##🎜🎜# 실제 애플리케이션과 마찬가지로 자동 로딩은 bootstrap.php.cache
파일을 통해 자동으로 활성화되고 완료됩니다(이 부분의 기본 구성은 app/phpunit.xml.dist 파일에 있습니다). bootstrap.php.cache
文件来完成(这部分的配置默认是在app/phpunit.xml.dist文件中)
针对指定文件或目录的测试也很简单:
# run all tests of the application# 运行程序中的所有测试$ phpunit # run all tests in the Util directory# 运行指定目录下的所有测试$ phpunit tests/AppBundle/Util # run tests for the Calculator class# 仅运行Calculator类的测试$ phpunit tests/AppBundle/Util/CalculatorTest.php # run all tests for the entire Bundle# 运行整个bundle的测试$ phpunit tests/AppBundle/
功能测试 ¶
功能测试(Functional tests)检查程序不同层面的整合情况(从路由到视图)。这些层面本身并不因PHPUnit的介入而发生改变,只不过它们有着独特的工作流:
制造一个请求(request);
测试响应(response);
点击一个链接,或提交一个表单;
测试响应;
清除然后重复。
你的第一个功能测试 ¶
功能测试是存放在 Test/AppBundle/Controller
目录下的普通PHP文件。如果要测试由你的 PostController
处理的页面,先创建一个新的PostControllerTest.php文件,并继承一个特殊的 WebTestCase
类。
作为例程,这个测试看起来可能像下面代码:
// tests/AppBundle/Controller/PostControllerTest.phpnamespace Tests\AppBundle\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class PostControllerTest extends WebTestCase{ public function testShowPost() { $client = static::createClient(); $crawler = $client->request('GET', '/post/hello-world'); $this->assertGreaterThan( 0, $crawler->filter('html:contains("Hello World")')->count() ); }}
为了运行上面的功能测试, WebTestCase
类启动了程序内核。在多数情况下,这是自动完成的。但如果kernel位于非标准目录,你需要调整 phpunit.xml.dist
文件,重新设置 KERNEL_DIR
环境变量为你的kernel目录:
<?xml version="1.0" charset="utf-8" ?><phpunit> <php> <server name="KERNEL_DIR" value="/path/to/your/app/" /> </php> <!-- ... --></phpunit>
createClient()
1
| 응답 테스트 li> 링크를 클릭하거나 양식을 제출하세요. | 응답을 테스트하세요.
첫 번째 기능 테스트 ¶
🎜기능 테스트입니다.Test/AppBundle/Controller
디렉터리에 저장된 일반 PHP 파일입니다. PostController
에서 처리하는 페이지를 테스트하려면 먼저 새 PostControllerTest.php 파일을 만들고 특수 WebTestCase
클래스를 상속하세요. 🎜🎜루틴적으로 이 테스트는 다음 코드와 유사할 수 있습니다. 🎜$crawler = $client->request('GET', '/post/hello-world');🎜🎜🎜
WebTestCase
클래스가 시작되었습니다. 프로그램 커널. 대부분의 경우 이 작업은 자동으로 수행됩니다. 그러나 커널이 비표준 디렉터리에 있는 경우 phpunit.xml.dist
파일을 조정하고 KERNEL_DIR
환경 변수를 커널 디렉터리로 재설정해야 합니다. 🎜 🎜🎜🎜🎜$link = $crawler ->filter('a:contains("Greet")') // 选择所有含有"Greet"文本之链接 ->eq(1) // 结果列表中的第二个 ->link() // 点击它; $crawler = $client->click($link);🎜
createClient()
메서드는 클라이언트를 반환하며, 이 클라이언트는 웹사이트 페이지를 크롤링할 수 있도록 브라우저를 시뮬레이션하는 데 사용할 수 있습니다. 🎜🎜🎜🎜🎜🎜🎜🎜$form = $crawler->selectButton('submit')->form(); // 设置一些值$form['name'] = 'Lucas';$form['form_name[subject]'] = 'Hey there!'; // 提交表单$crawler = $client->submit($form);🎜🎜🎜 🎜
// Assert that the response matches a given CSS selector.// 断言响应内容匹配到一个指定的CSS拾取器$this->assertGreaterThan(0, $crawler->filter('h1')->count());🎜🎜🎜🎜🎜
request() 메서드
(추가 요청 메서드request()方法
(参考 更多请求方法)返回了一个 Crawler
对象,用于从响应内容中选择元素(select elements),完成点击链接或提交表单这样的动作。
响应信息必须是XML或HTML文档格式,抓取器(Crawler)才会工作。若需要不带文档格式的纯响应内容(raw content),请使用 $client->getResponse()->getContent()
。
需要点击链接时,先用抓取器选择它,可使用XPath表达式或CSS拾取器来完成选 择,然后再使用client行为来点击它:
$this->assertContains( 'Hello World', $client->getResponse()->getContent());
提交表单时非常相似:选取一个表单按钮,可选地覆写某些表单项的值,然后提交对应的表单:
use Symfony\Component\HttpFoundation\Response; // ... // Assert that there is at least one h2 tag// with the class "subtitle"// 断言至少有一个h2标签,其class是subtitle$this->assertGreaterThan( 0, $crawler->filter('h2.subtitle')->count()); // Assert that there are exactly 4 h2 tags on the page// 断言页面有4个h2标签$this->assertCount(4, $crawler->filter('h2')); // Assert that the "Content-Type" header is "application/json"// 断言Content-Type头是application/json$this->assertTrue( $client->getResponse()->headers->contains( 'Content-Type', 'application/json' )); // Assert that the response content contains a string// 断言响应信息中包含一个字符串$this->assertContains('foo', $client->getResponse()->getContent());// ...or matches a regex$this->assertRegExp('/foo(bar)?/', $client->getResponse()->getContent()); // Assert that the response status code is 2xx// 断言响应状态码是2xx$this->assertTrue($client->getResponse()->isSuccessful());// Assert that the response status code is 404// 断言响应状态码是404$this->assertTrue($client->getResponse()->isNotFound());// Assert a specific 200 status code// 断言响应状态码是特殊的200$this->assertEquals( 200, // or Symfony\Component\HttpFoundation\Response::HTTP_OK $client->getResponse()->getStatusCode()); // Assert that the response is a redirect to /demo/contact// 断言响应是一个指向/demo/contact的跳转$this->assertTrue( $client->getResponse()->isRedirect('/demo/contact'));// ...or simply check that the response is a redirect to any URL// 或者仅言响应是一个跳转,不管指向的URL是什么$this->assertTrue($client->getResponse()->isRedirect());
表单也可以处理上传,它还包含了用于填写不同类型的表单字段的方法(例如 select()
和 tick()
참조)는 Crawler
개체, 클릭 링크를 완성하기 위해 응답 콘텐츠(요소 선택)에서 요소를 선택하는 데 사용됨 또는 양식 제출과 같은 작업.
$client->getResponse()->getContent()
를 사용하세요. 1매우 좋습니다. 양식을 제출할 때와 유사합니다. 양식 버튼을 선택하고 선택적으로 특정 양식 항목의 값을 덮어쓴 다음 해당 양식을 제출합니다.
$crawler = $client->request('GET', '/post/hello-world');
select()
및 tick()<)를 채우는 메서드를 포함합니다. /코드>). 자세한 내용은 다음 섹션 유용한 어설션
가능한 한 빨리 테스트를 마스터할 수 있도록 다음 예제에는 가장 일반적으로 사용되며 유용한 테스트 어설션이 나열되어 있습니다.
$link = $crawler->selectLink('Go elsewhere...')->link();$crawler = $client->click($link); $form = $crawler->selectButton('validate')->form();$crawler = $client->submit($form, array('name' => 'Fabien'));
HTTP 상태 코드 상수는 Symfony 2.4에서 도입되었습니다. 테스트 클라이언트 사용 ¶ 테스트 클라이언트는 브라우저처럼 HTTP 클라이언트를 시뮬레이션하고 Symfony 프로그램에 대한 요청을 생성할 수 있습니다.
🎜🎜// Directly submit a form (but using the Crawler is easier!)// 直接提交表单(但是使用Crawler更容易些)$client->request('POST', '/submit', array('name' => 'Fabien')); // Submit a raw JSON string in the request body// 在请求过程中提交一个JSON原生串$client->request(
'POST',
'/submit',
array(),
array(),
array('CONTENT_TYPE' => 'application/json'),
'{"name":"Fabien"}'); // Form submission with a file upload// 文件上传表单的提交use Symfony\Component\HttpFoundation\File\UploadedFile; $photo = new UploadedFile(
'/path/to/photo.jpg',
'photo.jpg',
'image/jpeg',
123);$client->request(
'POST',
'/submit',
array('name' => 'Fabien'),
array('photo' => $photo)); // Perform a DELETE request and pass HTTP headers// 执行一个DELETE请求并传递HTTP头$client->request(
'DELETE',
'/post/12',
array(),
array(),
array('PHP_AUTH_USER' => 'username', 'PHP_AUTH_PW' => 'pa$$word'));
🎜🎜🎜🎜1
🎜🎜🎜🎜🎜request()
메서드는 HTTP 요청 매개변수와 URL 매개변수를 받아들이고 크롤러 인스턴스를 반환합니다. request()
方法接受一个HTTP请求方式的参数和一个URL参数,返回一个Crawler实例。
对于功能测试来说,写死request链接是最佳实践。如果在测试中生成URL时使用Symfony路由,它将无法侦测到针对此URL页面的任何改变,这可能导致用户体验受到冲击。
使用抓取器来找到响应内容中的DOM元素。这些元素可以被用在点击链接或提交表单等场合:
$history = $client->getHistory();$cookieJar = $client->getCookieJar();
此处的 click()
方法和 submit()
方法,都会返回一个 crawler
抓取器对象。这些方法是浏览你的程序页面的最佳方式,因为它们帮你做了很多事,像是从表单中侦测HTTP请求方式,或者给你提供一个很好的API用于文件上传。
在后面的 Crawler 小节中你将学习到更多关于链接Link和表单Form对象的知识。
request
기능 테스트의 경우 요청 링크를 하드코딩하는 것이 가장 좋습니다. 테스트에서 URL을 생성할 때 Symfony 라우팅을 사용하면 URL 페이지의 변경 사항을 감지할 수 없어 사용자 경험이 손상될 수 있습니다.