浏览器模拟器和 Mink

浏览器模拟器是模拟或模仿网络浏览器功能和行为的程序。Behat 或 Codeception 等程序可以使用这些模拟器来模拟真实用户在使用您的应用程序时在网络浏览器上的操作。

浏览器模拟器有两种类型:

  • 无头模拟器(Headless):这些类型的模拟器会触发 HTTP 请求,并简单地监听网络应用程序返回的 DOM 或响应。它们最适合轻量级测试,无需进行复杂的检查,如在鼠标悬停事件后检查 AJAX 响应。

  • 控制器(Controllers):这类模拟器使用真实浏览器,基本上就像一个人在控制真实浏览器。根据我的经验,使用这类模拟器的好处是,我们可以设置要测试的浏览器类型。我们还可以检查页面上的 JavaScriptAJAX 结果。

在我们的示例中,我们将使用无头浏览器,因为我们不需要执行任何 JavaScript/AJAX 操作。如果您需要为您的项目使用真正的浏览器模拟器,我强烈建议使用 Selenium2。您可以从 Selenium 网站 https://www.selenium.dev 阅读有关 Selenium 的更多信息。

接下来,为了让我们的 Behat 应用程序开始与浏览器模拟器交互(代替真实用户),请创建以下程序文件:

  1. 打开我们之前创建的 HomeContext.php 类并将其替换为以下内容:

    codebase/behat/features/bootstrap/HomeContext.php
    <?php
    
    use Behat\Mink\Mink;
    use Behat\Mink\Session;
    use Behat\Mink\Driver\GoutteDriver;
    use Behat\MinkExtension\Context\MinkContext;
    use Behat\MinkExtension\Context\MinkAwareContext;
    
    class HomeContext extends MinkContext implements MinkAwareContext
    {
        public function __construct()
        {
            $mink = new Mink([
                'goutte' => new Session(new
                    GoutteDriver()), // Headless browser
            ]);
            $this->setMink($mink);
            $this->getMink()->getSession('goutte')->start();
        }
    }

    在构造函数中,我们实例化了 Mink 的一个实例,并注入了一个 Session 对象。我们在会话中注入了一个驱动程序对象和一个 Goutte 无头模拟器实例。Mink 支持不同类型的浏览器仿真器,详情请点击 https://mink.behat.org/en/latest/at-a-glance.html

    接下来,在同一个类中添加以下函数。这些方法代表您在 scenarios 中定义的每个步骤:

    /**
    * @Given I have access to the home page URL
    */
    public function iHaveAccessToTheHomePageUrl()
    {
        return true;
    }
    
    /**
    * @When I visit the home page
    */
    public function iVisitTheHomePage()
    {
        // Using the Goutte Headless emulator
        $sessionHeadless = $this->getMink()->getSession('goutte');
        $sessionHeadless->visit("symfony/public");
        $sessionHeadless->getPage()->clickLink('Create your first page');
    }
    
    /**
    * @Then I should see the Symfony Logo
    */
    public function iShouldSeeTheSymfonyLogo()
    {
        // Headless emulator test:
        $assertHeadless = $this->assertSession('goutte');
        $assertHeadless->elementExists('css', '.logo');
        $assertHeadless->pageTextContains('Welcome To Symfony 6');
    }

    iVisitTheHomePage() 方法中,我们检索了刚刚创建的 Goutte 注入会话,然后让模拟器访问 URL 并单击链接。

  2. 现在,让我们运行测试,看看它是否有效!运行以下命令:

    /var/www/html/behat# ./vendor/bin/behat

    然后您应该看到以下结果:

    image 2023 10 23 20 47 10 159
    Figure 1. Figure 6.7 – Failed headless browser assertion

    我们的测试又失败了,但这是为什么呢?请注意,在 iVisitTheHomePage() 方法中,我们有以下行:

    $sessionHeadless->getPage()->clickLink('Create your first page');

    此行告诉模拟器单击主页上的 Tutorials 选项,该选项使用 Create your first page 锚文本:

    image 2023 10 23 20 49 26 602
    Figure 2. Figure 6.8 – Create your first page link

    模拟器成功加载了 Symfony 主页,然后点击了教程链接,结果浏览器被重定向到了另一个页面!这就是测试失败的原因。因此,如果我们更新 iVisitTheHomePage() 方法并删除这一行,现在就能通过测试了!

  3. 通过运行以下命令再次运行测试:

    /var/www/html/behat# ./vendor/bin/behat

    然后我们应该看到以下结果:

    image 2023 10 23 20 51 32 696
    Figure 3. Figure 6.9 – The first Behat test passed

    我们终于通过了第一个 Behat 测试!在 iShouldSeeTheSymfonyLogo() 方法中,您会注意到我们有两个断言。在第一个断言中,我们想要检查返回的 DOM 中是否存在一个元素,即 logo 元素。然后我们添加了另一个断言来检查 Welcome to Symfony 6 文本。

  4. 打开 Web 浏览器并访问以下页面: http://127.0.0.1:8081/symfony/public/

  5. 打开你的元素检查器;您应该看到 logo 元素。这就是我们告诉 Mink 寻找的内容:

    image 2023 10 23 20 54 15 968
    Figure 4. Figure 6.10 – Logo element

当浏览器模拟器访问主页时,logo 元素和 Welcome to Symfony 6 的文本都存在,因此最终通过了测试!

现在,我想你已经知道这些工具有多么有用和强大了。这可以为你和你的团队节省数小时的手动测试时间。

在这个阶段,您可以开始使用 Gherkin 语言编写由功能和场景代表的行为,然后使用 Behat 执行这些测试,再使用 PHP 开发功能来满足这些测试。如果您遵循这一流程,您的开发将由在编写一行代码之前就已定义的行为驱动。现在,您的开发就是行为驱动的!