시험


추가 코드 줄을 작성할 때마다 잠재적인 새로운 버그가 추가됩니다. 더 좋고 더 안정적인 프로그램을 구축하려면 코드에 기능 테스트와 단위 테스트를 사용해야 합니다.

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-* 옵션을 전달할 수 있습니다. 생성합니다. 도움말 정보를 보려면 —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
기능 테스트 기능 기능 테스트 다양한 수준의 프로그램 통합을 확인합니다(라우팅에서 보기까지). 이러한 레벨 자체는 PHPUnit의 개입으로 인해 변경되지 않지만 고유한 작업 흐름을 갖습니다. 응답 테스트 응답을 테스트하세요.
  • 지우고 반복하세요.
    • 요청하기
  • 링크를 클릭하거나 양식을 제출하세요.
  • 첫 번째 기능 테스트

    🎜기능 테스트입니다. 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 개체, 클릭 링크를 완성하기 위해 응답 콘텐츠(요소 선택)에서 요소를 선택하는 데 사용됨 또는 양식 제출과 같은 작업.

    크롤러가 작동하려면 응답 정보가 XML 또는 HTML 문서 형식이어야 합니다. 문서 형식이 없는 원시 콘텐츠가 필요한 경우 $client->getResponse()->getContent()를 사용하세요.

    링크를 클릭해야 하는 경우 먼저 그래버로 링크를 선택하세요. XPath 표현식이나 CSS 선택기를 사용하여 선택을 완료한 다음 클라이언트 동작을 사용하여 링크를 클릭할 수 있습니다.

    1

    매우 좋습니다. 양식을 제출할 때와 유사합니다. 양식 버튼을 선택하고 선택적으로 특정 양식 항목의 값을 덮어쓴 다음 해당 양식을 제출합니다.

    $crawler = $client->request('GET', '/post/hello-world');
    < div class="admonition admonition-tip ">

    양식은 업로드도 처리할 수 있으며 다양한 유형의 양식 필드(예: select()tick()<)를 채우는 메서드를 포함합니다. /코드>). 자세한 내용은 다음 섹션
    양식

    을 참조하세요.

    이제 페이지가 예상대로 작동하는지 테스트하는 어설션을 사용하여 프로그램을 쉽게 이동할 수 있습니다. 크롤러를 사용하여 DOM에서 어설션이 작동하도록 합니다.

    request(
        $method,
        $uri,
        array $parameters = array(),
        array $files = array(),
        array $server = array(),
        $content = null,
        $changeHistory = true)

    또는 콘텐츠에 특정 텍스트가 포함되어 있는지 확인하고 싶거나 응답 콘텐츠가 XML/HTML 형식이 아닌지 확인하려는 경우 응답 콘텐츠를 직접 테스트하세요.

    $client->request(
        'GET',
        '/post/hello-world',
        array(),
        array(),
        array(
            'CONTENT_TYPE'          => 'application/json',
            'HTTP_REFERER'          => '/foo/bar',
            'HTTP_X-Requested-With' => 'XMLHttpRequest',
        ));

    유용한 어설션

    가능한 한 빨리 테스트를 마스터할 수 있도록 다음 예제에는 가장 일반적으로 사용되며 유용한 테스트 어설션이 나열되어 있습니다.

    $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页面的任何改变,这可能导致用户体验受到冲击。

    以下是更多关于request()方法的例子:

    request()方法的完整用例:

    $client->insulate();

    其中的 server 数组存放了你可能期待使用的PHP超全局变量$_SERVER的原生键值。例如,设置 Content-TypeRefererX-Requested-With (HTTP头)时,你需要传入以下参数(注意用于非标准头的 HTTP_ 前缀):

    $client->back();$client->forward();$client->reload(); // Clears all cookies and the history// 清除所有cookie和历史记录$client->restart();

    使用抓取器来找到响应内容中的DOM元素。这些元素可以被用在点击链接或提交表单等场合:

    $history = $client->getHistory();$cookieJar = $client->getCookieJar();

    此处的 click() 方法和 submit() 方法,都会返回一个 crawler 抓取器对象。这些方法是浏览你的程序页面的最佳方式,因为它们帮你做了很多事,像是从表单中侦测HTTP请求方式,或者给你提供一个很好的API用于文件上传。

    在后面的 Crawler 小节中你将学习到更多关于链接Link和表单Form对象的知识。

    request

    기능 테스트의 경우 요청 링크를 하드코딩하는 것이 가장 좋습니다. 테스트에서 URL을 생성할 때 Symfony 라우팅을 사용하면 URL 페이지의 변경 사항을 감지할 수 없어 사용자 경험이 손상될 수 있습니다.


    다음은 request() 메소드의 추가 예입니다:

    request() 메소드의 전체 사용 사례:
    // the HttpKernel request instance// HttpKernel的请求实例$request = $client->getRequest(); // the BrowserKit request instance// 浏览器组件的请求实例$request = $client->getInternalRequest(); // the HttpKernel response instance// HttpKernel的响应实例$response = $client->getResponse(); // the BrowserKit response instance// 浏览器组件的响应实例$response = $client->getInternalResponse(); $crawler = $client->getCrawler();
    server 배열은 $_SERVER의 기본 키 값입니다. 예를 들어 Content-Type, Referer, X-Requested-With(HTTP 헤더)를 설정할 때 다음 매개변수를 전달해야 합니다. (비표준 헤더의 경우 HTTP_ 접두사 사용에 유의하세요):
    $container = $client->getContainer();$kernel = $client->getKernel();
    1
    다음 크롤러 섹션에서 이에 대해 알아볼 것입니다. 링크 및 양식 개체에 대해 자세히 알아보세요.
    스크레이퍼를 사용하여 응답 콘텐츠에서 DOM 요소를 찾습니다. 링크를 클릭하거나 양식을 제출할 때 다음 요소를 사용할 수 있습니다.
    여기서 click() 메서드와 submit() 메서드는 모두 크롤러 크롤러 개체. 이러한 방법은 양식에서 HTTP 요청 패턴을 감지하거나 파일 업로드를 위한 멋진 API를 제공하는 등 많은 작업을 수행하므로 애플리케이션 페이지를 탐색하는 가장 좋은 방법입니다.
    🎜요청 메서드를 사용하여 양식 제출을 직접 시뮬레이션하거나 더 복잡한 요청을 수행할 수도 있습니다. 몇 가지 유용한 예: 🎜
    $container = $client->getContainer();
    🎜마지막 알림으로, 동일한 스크립트에 여러 클라이언트가 있을 때 부작용을 피하기 위해 각 요청이 자체 PHP 프로세스에서 실행되도록 할 수 있습니다. 🎜🎜🎜🎜🎜🎜🎜🎜🎜
    // enable the profiler for the very next request// 为接下来的请求开启profiler$client->enableProfiler(); $crawler = $client->request('GET', '/profiler'); // get the profile 得到分析器$profile = $client->getProfile();
    🎜🎜🎜🎜
    1
    🎜🎜🎜🎜🎜

    browsing

    Client 개체는 실제 브라우저에서 많은 작업을 지원합니다.

    $crawler = $client->followRedirect();

    #🎜 🎜#내부 객체 사용

    getInternalRequest() 및 getInternalResponse() 메소드는 Symfony 2.3부터 도입되었습니다. 클라이언트를 사용하여 프로그램을 테스트하는 경우 클라이언트 내부의 일부 개체를 사용할 수도 있습니다.

    1

    요청이 격리되어 실행되지 않는 경우 를 사용할 수도 있습니다. 컨테이너(컨테이너) 및 커널(커널):
    $client->followRedirects();

    컨테이너 사용

    #🎜🎜 #기능 테스트는 응답만 테스트하는 것이 좋습니다. 그러나 드문 경우지만 내부 개체를 사용하여 어설션을 작성해야 할 수도 있습니다. 이때 종속성 주입 컨테이너(종속성 주입 컨테이너, 즉 서비스 컨테이너)를 호출할 수 있습니다. #🎜🎜 #

    1
    Container (容器)和 Kernel (内核):

    $client->followRedirects(false);

    使用容器 

    强烈推荐功能测试只测试响应。但在特定的罕见情况下,你可能要使用内部对象来书写断言。这时,你可以调用Dependency Injection Container(依赖注入容器,即服务容器):

    $newCrawler = $crawler->filter('input[type=submit]')
        ->last()
        ->parents()
        ->first();
    $crawler
        ->filter('h1')
        ->reduce(function ($node, $i) {
            if (!$node->getAttribute('class')) {
                return false;
            }
        })
        ->first();

    注意,如果你是把client隔离运行或者使用一个HTTP layer的话,上述功能无效。程序中的可用服务列表,你可通过 debug:container 命令行工具来查看。

    在Symfony2.6之前这个命令是 container:debug

    如果你需要检查的信息在分析器(profiler)中可用,那么应使用profiler来替代container。

    使用分析数据 

    每一次请求,你都可以借助Symfony分析器(profiler)来收集关于该请求在内部被处理的有关信息。例如,分析器常被用于验证指定页面在加载过程中的数据库查询次数是否小于给定值。

    为了得到最近一次请求的Profiler,按下例操作:

    // 返回第一个节点的属性值$crawler->attr('class'); // 返回第一个节点的节点文本$crawler->text(); // Extracts an array of attributes for all nodes// (_text returns the node value)// returns an array for each element in crawler,// each with the value and href// 提取一个由所有节点的属性组成的数组// (_text返回节点值)// 返回一个由抓取器中的每一个元素所组成的数组// 每个元素有value和href$info = $crawler->extract(array('_text', 'href')); // Executes a lambda for each node and return an array of results// 对每个节点执行一次lambda函数(即匿名函数),最后返回结果数组$data = $crawler->each(function ($node, $i) {
        return $node->attr('href');});

    在测试中使用分析器的某些细节,请参阅 如何在功能测试中使用分析器 一文。

    重定向 

    当一个请求返回的是重定向响应时,client并不自动跟进。你可以检测该响应信息,然后通过 followRedirect()

    1
    확인해야 할 정보가 프로파일러에 있다면, 컨테이너 대신 프로파일러를 사용해야 합니다.
    #🎜 🎜# #🎜 🎜 #클라이언트를 단독으로 실행하거나 HTTP 레이어를 사용하는 경우 위 기능이 작동하지 않으니 주의하세요. debug:container 명령줄 도구를 통해 프로그램에서 사용 가능한 서비스 목록을 볼 수 있습니다.
    Symfony2.6 이전에는 이 명령이 container:debug 였습니다.
    #🎜🎜##🎜🎜#분석 데이터 사용 ¶#🎜🎜##🎜🎜##🎜🎜 #각 요청에 대해 Symfony 프로파일러를 사용하여 요청이 내부적으로 처리되는 방식에 대한 관련 정보를 수집할 수 있습니다. 예를 들어 분석기는 지정된 페이지를 로드하는 동안 데이터베이스 쿼리 수가 지정된 값보다 작은지 확인하는 데 자주 사용됩니다. #🎜🎜##🎜🎜#최신 요청의 프로파일러를 얻으려면 다음 예를 따르세요. #🎜🎜#
    $crawler->selectLink('Click here');
    #🎜🎜##🎜🎜#테스트에서 프로파일러 사용에 대한 자세한 내용은 < a href ="/doc/current/cookbook/testing/profiling.html">기능 테스트에서 프로파일러를 사용하는 방법 #🎜🎜# 기사. #🎜🎜##🎜🎜#Redirect
    ¶#🎜🎜##🎜🎜##🎜🎜#요청이 리디렉션을 반환할 때 응답할 때, 클라이언트는 자동으로 후속 조치를 취하지 않습니다. 응답 메시지를 감지한 다음 followRedirect() 메서드를 통해 강제로 팔로우할 수 있습니다. #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜## 🎜 🎜##🎜🎜#
    $link = $crawler->selectLink('Click here')->link(); $client->click($link);
    #🎜🎜##🎜🎜##🎜🎜##🎜🎜#
    1
    #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#

    클라이언트가 모든 리디렉션을 자동으로 따르도록 해야 하는 경우 followRedirects() 메서드를 사용하여 강제로 구현할 수 있습니다. followRedirects() 方法:

    $buttonCrawlerNode = $crawler->selectButton('submit');
    1

    false 传给 followRedirects()

    $form = $buttonCrawlerNode->form();
    $form = $buttonCrawlerNode->form(array(
        'name'              => 'Fabien',
        'my_form[subject]'  => 'Symfony rocks!',));
    🎜🎜 falsefollowRedirects() 메서드에 전달하면 리디렉션이 더 이상 따르지 않습니다. 🎜🎜🎜🎜🎜🎜🎜🎜
    1
    🎜🎜 🎜🎜
    $form = $buttonCrawlerNode->form(array(), 'DELETE');
    🎜🎜🎜🎜🎜

    Crawler

    클라이언트를 통해 요청할 때마다 Crawler 인스턴스가 반환됩니다. 스크레이퍼를 사용하면 HTML 문서를 탐색하고, DOM 노드를 선택하고, 링크와 양식을 찾을 수 있습니다.

    Traversing

    JQuery와 마찬가지로 크롤러에는 HTML/XML 문서의 DOM을 탐색하는 다양한 방법이 있습니다. 예를 들어, 다음 메소드는 모든 input[type=submit] 요소를 찾고 페이지의 마지막 요소를 선택한 다음 인접한 상위 요소를 선택합니다. input[type=submit] 元素,并选择页面中的最后一个,然后选择它的临近父元素:

    1

    还有很多其他方法可以利用:

    • filter('h1.title')
    • 匹配CSS拾取器的所有节点。
    • filterXpath('h1')
    • 匹配XPath expression(表达式)的所有节点。
    • eq(1)
    • 指定索引的节点。
    • first()
    • 第一个节点。
    • last()
    • 最后一个节点。
    • siblings()
    • Siblings。
    • nextAll()
    • 后续所有siblings。
    • previousAll()
    • 之前所有siblings。
    • parents()
    • 返回所有父节点。
    • children()
    • 返回所有子节点。
    • reduce($lambda)
    • 匿名函数$lambda不返回false时的所有节点。

    由于上述每个方法都返回一个 Crawler 抓取器对象,你可以通过对各方法的链式调用来减少节点拾取过程的代码:

    $client->submit($form);

    可以使用 count() 函数来得到存储在一个Crawler中的节点数量: count($crawler)

    提取信息 

    抓取器可以从节点中提到信息:

    $client->submit($form, array(
        'name'              => 'Fabien',
        'my_form[subject]'  => 'Symfony rocks!',));

    链接 

    为了选择链接,你可以使用上述遍历方法,或者使用更方便的 selectLink()

    // 改变某个字段的值/Change the value of a field$form['name'] = 'Fabien';$form['my_form[subject]'] = 'Symfony rocks!';

    다른 많은 메소드가 있습니다. 사용됨:
    • filter('h1.title')
    • 일치하는 모든 노드 CSS 선택기 .
    • filterXpath('h1')
    • XPath 표현식(expression)과 일치하는 모든 노드.
    • eq(1)
    • 색인을 지정하는 노드입니다.
    • first()
    • 첫 번째 노드입니다.
    • last()
    • 마지막 노드입니다.
    • 형제자매()
    • 형제자매.
    • nextAll()
    • 이후의 모든 형제.
    • previousAll()
    • 모든 이전 형제.
    • parents()
    • 모든 상위 노드를 반환합니다.
    • children()
    • 모든 하위 노드를 반환합니다.
    • reduce($lambda)
    • 익명 함수 $lambda가 false를 반환하지 않는 경우 모든 노드.
    위의 각 메서드는 Crawler 그래버 개체를 반환하므로 각 메서드에 대한 호출을 연결하여 노드 선택 프로세스의 코드를 줄일 수 있습니다.
    // 选取一个option单选或radio单选$form['country']->select('France'); // 选取一个checkbox$form['like_symfony']->tick(); // 上传一个文件$form['photo']->upload('/path/to/lucas.jpg');
    < div class="admonition admonition-tip">크롤러는 노드에서 정보를 추출할 수 있습니다:
    // Get the form. 取得表单$form = $crawler->filter('button')->form(); // Get the raw values. 取得原始数值$values = $form->getPhpValues(); // Add fields to the raw values. 给原始数组添加新字段$values['task']['tag'][0]['name'] = 'foo';$values['task']['tag'][1]['name'] = 'bar'; // Submit the form with the existing and new values.// 提交表单,包括既有值,以及新值$crawler = $this->client->request($form->getMethod(), $form->getUri(), $values,
        $form->getPhpFiles()); // The 2 tags have been added to the collection.// 2个新标签被添加到collection中$this->assertEquals(2, $crawler->filter('ul.tags > li')->count());
    count() 함수를 사용하여 크롤러에 저장된 노드 수를 가져올 수 있습니다: count($crawler)
    정보 추출
    Link ¶🎜
    🎜🎜링크를 선택하려면 위의 순회 방법을 사용하거나 보다 편리한 selectLink() 단축키 방법을 사용할 수 있습니다.🎜 🎜🎜🎜🎜🎜🎜🎜
    // Get the values of the form. 取得表单数据$values = $form->getPhpValues(); // Remove the first tag. 移除第一个标签unset($values['task']['tags'][0]); // Submit the data. 提交数据$crawler = $client->request($form->getMethod(), $form->getUri(),
        $values, $form->getPhpFiles()); // The tag has been removed. 标签已被移除$this->assertEquals(0, $crawler->filter('ul.tags > li')->count());
    🎜🎜🎜🎜
    PHP:// app/config/config_test.php // ...$container->loadFromExtension('swiftmailer', array(
        'disable_delivery' => true,));
    🎜🎜🎜🎜🎜

    이를 사용하면 주어진 텍스트가 포함된 모든 링크 또는 주어진 텍스트가 포함된 alt 속성이 있는 클릭 가능한 이미지를 선택할 수 있습니다. 다른 필터링 방법과 마찬가지로 Crawler 개체도 반환합니다. alt 属性中包含了给定文本。和其他的过滤方法类似,它也是返回一个 Crawler 对象。

    一旦你选中了一个链接(link),你就可以使用一个特殊的链接对象( link  object),它是一个专门用来处理链接的方法(类似 getMethod()getUri() 这种,都属于帮助方法/helpful method)。要点击链接,使用Client的 click() 方法,并把链接对象传进去:

    XML:<!-- app/config/config_test.xml --><?xml version="1.0" encoding="UTF-8" ?><container xmlns="http://symfony.com/schema/dic/services"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:swiftmailer="http://symfony.com/schema/dic/swiftmailer"    xsi:schemaLocation="http://symfony.com/schema/dic/services        http://symfony.com/schema/dic/services/services-1.0.xsd        http://symfony.com/schema/dic/swiftmailer        http://symfony.com/schema/dic/swiftmailer/swiftmailer-1.0.xsd">     <!-- ... -->
        <swiftmailer:config disable-delivery="true" /></container>

    表单 

    表单可以通过它们的按钮被选择,而按钮可以用selectButton()方法来选择,正如选择链接一样:

    YAML:# app/config/config_test.yml # ...swiftmailer:
        disable_delivery: true
    $client = static::createClient(array(
        'environment' => 'my_test_env',
        'debug'       => false,));

    注意你选择的是表单的按钮而不是表单本身,因为表单可以有多个按钮。如果你使用遍历API,记住必须要找到一个按钮。

    selectButton() 方法可以选中 button (按钮)标签,以及submit(提交)所在的标签(即 input 标签)。它使用按钮的几个部分来找到它们:

    • value 属性值(The value attribute value)

    • 图片按钮的 id 属性值或 alt 属性值(The id or alt attribute value for images)

    • button 标签的 id 属性值或 name 属性值(The id or name attribute value for button tags)

    当你有了一个含有button的crawler之后,调用 form() 方法即可得到拥有这个button节点的form实例。

    $client = static::createClient(array(), array(
        'HTTP_HOST'       => 'en.example.com',
        'HTTP_USER_AGENT' => 'MySuperBrowser/1.0',));
    $client->request('GET', '/', array(), array(), array(
        'HTTP_HOST'       => 'en.example.com',
        'HTTP_USER_AGENT' => 'MySuperBrowser/1.0',));

    当调用 form()

    링크를 선택하면 링크를 처리하는 데 특별히 사용되는 메서드인 특수 링크 개체(link 개체)를 사용할 수 있습니다(getMethod( ) 또는 getUri()는 모두 유용한 메서드입니다. 링크를 클릭하려면 클라이언트의 click() 메소드를 사용하고 링크 객체를 다음 위치에 전달하세요.

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

    Form

    양식은 버튼을 통해 선택할 수 있으며 버튼은 링크 선택과 마찬가지로 selectButton() 메서드를 사용하여 선택할 수 있습니다.
    <!-- app/phpunit.xml.dist --><phpunit>
        <!-- ... -->
        <testsuites>
            <testsuite name="Project Test Suite">
                <!-- ... - - ->            <directory>../lib/tests</directory>        </testsuite>    </testsuites>    <!-- ... - - -></phpunit>
    <!-- app/phpunit.xml.dist --><phpunit>
        <!-- ... -->
        <filter>
            <whitelist>
                <!-- ... -->
                <directory>../lib</directory>
                <exclude>
                    <!-- ... -->
                    <directory>../lib/tests</directory>
                </exclude>
            </whitelist>
        </filter>
        <!-- ... - - -></phpunit>
    🎜🎜🎜
    🎜 양식 자체가 아닌 양식의 버튼을 선택한다는 점에 유의하세요. 양식에 여러 개의 버튼이 있을 수 있기 때문입니다. 순회 API를 사용하는 경우 버튼을 찾아야 한다는 점을 기억하세요. 🎜🎜🎜🎜selectButton() 메소드는 버튼(버튼) 라벨과 제출(submit)이 위치한 라벨(예: 입력)을 선택할 수 있습니다. 라벨) . 이를 찾기 위해 버튼의 여러 부분을 사용합니다: 🎜
    • 🎜value 값 속성 값 🎜
    • 🎜이미지 버튼의 ID 속성 값 또는 alt 속성 값(이미지의 id 또는 alt 속성 값)🎜
    • 🎜button 태그의 id 속성 값 또는 name 속성 값(버튼 태그의 id 또는 name 속성 값)🎜
    🎜버튼이 포함된 크롤러가 있는 경우 < code>form() 메서드를 사용하여 이 버튼 노드를 소유한 양식 인스턴스를 가져옵니다. 🎜🎜🎜🎜🎜🎜🎜🎜rrreee🎜🎜🎜🎜rrreee🎜🎜🎜🎜🎜🎜🎜🎜 form() 메서드를 호출할 때 양식 필드 값이 포함된 배열을 전달할 수도 있습니다. in, 기본값을 대체하려면: 🎜rrreee🎜 특정 HTTP 양식 제출 방법을 시뮬레이션하려면 이를 두 번째 매개변수로 전달하십시오.

    클라이언트는 양식 인스턴스를 제출할 책임이 있습니다.

    rrreee
    rrreee

    필드 값은 submit() 메소드의 두 번째 매개변수로 전달될 수 있습니다:

    rrreee

    더 복잡한 상황에서는 양식 인스턴스를 배열로 사용하여 각 필드에 해당하는 값을 설정할 수 있습니다:

    rrreee

    유형에 따라 필드 값을 관리하는 데 유용한 API도 있습니다.

    rrreee

    의도적으로 "잘못된" 선택/라디오 값을 선택하려는 경우 잘못된 선택 값 선택 을 참조하세요.

    Form 개체의 getValues() 메서드를 호출하여 제출하려는 양식 필드 값을 가져올 수 있습니다. 업로드된 파일은 getFiles() 메서드에서 반환된 분리된 배열에서도 얻을 수 있습니다. getPhpValues()getPhpFiles() 메서드도 제출된 필드를 반환할 수 있지만 PHP 형식입니다( my_form[subject와 같이 대괄호로 묶인 키를 사용합니다). ] – PHP 배열로 변환됨). getValues() 方法即可。已上传的文件也可以从一个分离出来的数组得到,这个数组由 getFiles() 方法返回。 getPhpValues() 以及 getPhpFiles() 方法同样可以返回已经提交的字段,只不过是PHP格式的(它把带有方括号的键 – 比如 my_form[subject]  – 给转换成PHP数组)。

    添加或删除表单到Collection 

    如果你使用了 Collection of Forms(表单集合),你不能对既有表单添加一个 $form['task[tags][0][name]'] = 'foo 字段。这会导致一个 Unreachable field "…" 错误。因为 $form 只能被用于设置现有的字段。为了添加一个新字段,你不得不把值添加到一个原始数组中:

    rrreee

    这里的 task[tags][0][name] 就是由JavaScript创建的字段的名字。

    你可以移除一个既有字段,比如一个标签(tag):

    rrreee

    配置测试 

    功能测试所用到的Client创建了一个Kernel,用于在一个特殊的 test 测试环境中运行。由于Symfony在测试时加载的是 app/config/config_test.yml

    에서는 $form['task[tags][0][name]'] = 'foo 필드에 추가할 수 없습니다. 이로 인해 접근할 수 없는 필드 "..." 오류가 발생합니다. $form은 기존 필드를 설정하는 데에만 사용할 수 있기 때문입니다. 새 필드를 추가하려면 기본 배열에 값을 추가해야 합니다. 🎜rrreee🎜 여기서 task[tags][0][name]은 JavaScript로 생성된 필드의 이름입니다. 🎜🎜🎜태그와 같은 기존 필드를 제거할 수 있습니다. 🎜rrreee🎜구성 테스트 ¶🎜🎜🎜🎜기능 테스트 사용된 클라이언트가 생성합니다. 특별한 test 테스트 환경에서 실행하기 위한 커널입니다. Symfony는 테스트 시 app/config/config_test.yml을 로드하므로 테스트에 사용되는 "프로그램 수준" 설정을 조정할 수 있습니다. 🎜🎜예를 들어 기본 Swift Mailer는 테스트 환경에서 이메일을 보내지 않도록 설정되어 있습니다. 구성 파일의 관련 옵션은 다음과 같이 설정됩니다: 🎜rrreeerrreee🎜rrreee🎜

    완전히 다른 환경을 사용하거나 관련 옵션을 createClient() 메서드에 전달하여 기본 디버그 모드( true )를 재정의할 수도 있습니다. true ),通过把相关选项传给 createClient() 方法即可:

    rrreee

    如果你的程序需要通过一些HTTP头才能运转,把它们传给createClient()方法的第二个参数:

    rrreee

    你也可以在每一个request基本过程中覆写HTTP header:

    rrreee

    client在 test 测试环境下是容器中的可用服务(或者无论什么环境,只要 framework.test选项被开启)。这意味着只要需要,你可以覆写整个client服务。


    PHPUnit配置 

    每一个程序,有它自己的PHPUnit配置,就存在 app/phpunit.xml.dist 文件中。你可以编辑这个文件,改变默认值,或创建一个仅供你本地机器设定测试选项的 app/phpunit.xml 文件。

    app/phpunit.xml.dist 文件存在你的代码宝库中并且忽略 app/phpunit.xmlrrreee

    프로그램을 실행하기 위해 일부 HTTP 헤더를 전달해야 하는 경우 이를 createClient() 메서드의 두 번째 매개변수에 전달하세요.
    rrreee#🎜🎜 #다음과 같이 할 수도 있습니다. 각 요청 기본 프로세스에서 HTTP 헤더를 덮어씁니다:

    rrreee

    client in test 테스트 환경은 컨테이너에서 사용 가능한 서비스입니다(또는 framework.test 옵션이 켜져 있는 한 어떤 환경이든 관계 없음). 에). 이는 필요할 때마다 전체 클라이언트 서비스를 재정의할 수 있음을 의미합니다.


    PHPUnit 구성

    # 🎜🎜#각 프로그램에는 app/phpunit.xml.dist 파일에 저장되는 자체 PHPUnit 구성이 있습니다. 이 파일을 편집하여 기본값을 변경하거나 로컬 시스템에 대해서만 테스트 옵션을 설정하는 app/phpunit.xml 파일을 생성할 수 있습니다.

    app/phpunit.xml.dist 파일이 존재합니다 저장소에 있고 app/phpunit.xml 파일을 무시하세요.

    기본값은 표준 디렉터리에만 저장됩니다(src/
    /#🎜🎜#Bundle/Tests, src/#🎜🎜#/Bundle/ #🎜 🎜#Bundle/Tests, src/*Bundle/Tests) 사용자 정의 번들의 테스트는 phpunit 명령으로 실행할 수 있습니다. 이는 app/phpunit.xml.dist 파일에 이미 구성되어 있습니다: #🎜🎜#rrreee#🎜🎜# 그러나 더 많은 디렉토리를 쉽게 추가할 수 있습니다. 예를 들어 다음 구성은 사용자 정의 디렉터리 lib/tests에 테스트를 추가합니다.#🎜🎜##🎜🎜#rrreee#🎜🎜#코드 적용 범위에 다른 디렉터리를 포함하려면 #🎜🎜# 코드도 추가해야 합니다. 발췌문: #🎜 🎜##🎜🎜##🎜🎜#rrreee#🎜🎜#