By Benjamin Eberlei, first published at Tue, 05 Apr 2016 10:00:00 +0200
Download our free e-book "Crafting Quality Software" with a selection of the finest blog posts as PDF or EPub.
You can also buy a printed version of the book on Amazon or on epubli.
Another day for a short PHPUnit trick. If you want to use PHPunit to control a browser for functional or acceptence tests, then you can easily do this using the Mink library. Mink is well known from the Behat community to facilitate Behaviour-Driven Development (BDD), but it is a standalone library that can be used with PHPUnit just as easily.
This is more flexible than using dedicated browser abstractions such as Selenium directly from PHPunit, because you can switch between different implementations or even run tests with multiple implementations using the same code base.
To start install Mink into your PHP project using Composer:
$ composer require behat/mink behat/mink-goutte-driver --dev
This will install Mink and the Guzzle/Goutte based Driver to crawl your site using a very simple cURL based browser abstraction.
Lets start using it for a simple PHPUnit test that verifies Wikipedia Search:
<?php
class WikipediaTest extends \PHPUnit_Framework_TestCase
{
public function testSearch()
{
$baseUrl = 'https://en.wikipedia.org/wiki/Main_Page';
$driver = new \Behat\Mink\Driver\GoutteDriver();
$session = new \Behat\Mink\Session($driver);
$session->start();
$session->visit($baseUrl);
$page = $session->getPage();
$page->fillField('search', 'PHP');
$page->pressButton('searchButton');
$content = $session->getPage()->getContent();
$this->assertContains('PHP: Hypertext Preprocessor', $content);
$this->assertContains('Rasmus Lerdorf', $content);
}
}
Setting up the Driver and Session over and over again can become quite complicated, lets introduce a reusable trait:
<?php
trait MinkSetup
{
private $minkBaseUrl;
private $minkSession;
/**
* @before
*/
public function setupMinkSession()
{
$this->minkBaseUrl = isset($_SERVER['MINK_BASE_URL'])
? $_SERVER['MINK_BASE_URL']
: 'http://localhost:8000';
$driver = new \Behat\Mink\Driver\GoutteDriver();
$this->minkSession= new \Behat\Mink\Session($driver);
$this->minkSession->start();
}
public function getCurrentPage()
{
return $this->minkSession->getPage();
}
public function getCurrentPageContent()
{
return $this->getCurrentPage()->getContent();
}
public function visit($url)
{
$this->minkSession->visit($this->minkBaseUrl . $url);
}
}
The @before
annotation is relatively new, it makes sure that the annotated method is called during each test cases setup phase, whenever we use the MinkSetup
trait in a test class.
Get a kickstart when writing new tests with a testing workshop by Qafoo.
This allows us to write the actual test in a much simpler way:
<?php
class WikipediaTest extends \PHPUnit_Framework_TestCase
{
use MinkSetup;
public function testSearch()
{
$this->visit('/');
$page = $this->getCurrentPage();
$page->fillField('search', 'PHP');
$page->pressButton('searchButton');
$content = $this->getCurrentPageContent();
$this->assertContains('PHP: Hypertext Preprocessor', $content);
$this->assertContains('Rasmus Lerdorf', $content);
}
}
If you followed the MinkSetup
implementation, you saw the MINK_BASE_URL
environemnt variable. We can configure this from the phpunit.xml
configuration:
<?xml version="1.0" ?>
<phpunit bootstrap="vendor/autoload.php">
<php>
<env name="MINK_BASE_URL">http://en.wikipedia.org/wiki</env>
</php>
</phpunit>
You can improve this by adding more helper methods onto the MinkSetup
trait, for example by closely following the possibilities that Mink provides inside of Behat (See MinkContext).
Stay up to date with regular new technological insights by subscribing to our newsletter. We will send you articles to improve your developments skills.
Sebastian Bergmann on Tue, 05 Apr 2016 14:42:48 +0200
Hello Benjamin,
Link to commentthank you for writing an article that I have been wanting to write for a while -- now I do not need to write it anymore.
In case you are interested, there is a ready-to-use trait available at https://github.com/sebastianbergmann/phpunit-mink-trait. It does (more or less) what your trait does.
Best,
Sebastian
Fabian on Mon, 11 Apr 2016 17:02:10 +0200
Hello,
Link to commentI'm wondering why not just use Behat directly for executing tests with Mink? Behats Cumcumber language is nice to read and everything work's out of the box.
Alvin Bunk on Wed, 03 Aug 2016 20:03:51 +0200
Hi there Benjamin.
Link to commentThank you for posting this. I was able to get Mink PHPUnit tests working because of this article and it helped me simplify my setup/testing.
I created an article as well referencing your article:
https://alvinbunk.wordpress.com/2016/08/03/using-mink-to-perform-functional-tests-in-symfony3-framework/
Regarding Fabian's comment on using Behat directly, I find using Mink is much easier to understand.