Introduction
I was struggling to use the Symfony3 Goutte Web Scraper to create PHPUnit Functional tests; this is mainly because the Goutte Web Scraper is a headless browser and can’t handle JavaScript or AJAX web pages. In my application I had a few JavaScript functions on certain pages, so the tests had to be done in a browser. I’ve used Selenium a lot before, but not in PHPUnit.
I did a lot of searching online to see what I could find, and thanks to Benjamin Eberlei‘s on Using Mink in PHPUnit and also Andrew Chan‘s Set up and run Selenium on CentOS articles, I was able to figure out how to get the Selenium2Driver working with Mink.
Installing & Setup
To install Mink in your Symfony3 project, use the following command:
composer require behat/mink
You’ll need to install the Selenium2Driver as well:
composer require behat/mink-selenium2-driver
Installing PHPUnit might depend on what OS you are using, so just follow the installation instructions. Make sure you run –self-update to get the latest version.
You’ll need the latest Java version. How you install, will depend on the OS you are using, but I happen to have CentOS:
yum install java-1.8.0-openjdk-devel.i686
Since CentOS is a server OS, it also doesn’t have X Window System installed nor does it have a FireFox browser, and you’ll need this to do Selenium2Driver tests. So install FireFox and X with the following commands (this can take a long time):
yum -y install firefox Xvfb libXfont Xorg
yum -y groupinstall "X Window System" "Desktop" "Fonts" "General Purpose Desktop"
You’ll also need to download the selenium-server-standalone JAR file. I used the version 2.53 JAR file here: https://selenium-release.storage.googleapis.com/2.53/selenium-server-standalone-2.53.1.jar
Important: You need to use version 2.53 or older versions of the JAR file, since newer versions of the JAR may not work with the version of FireFox installed.
After installing X Window System, you’ll need access to a direct console (preferably as an admin) and then run “startx” to bring up X and the GUI. Open up one terminal window and run the following command:
nohup java -jar selenium-server-standalone-2.53.1.jar
Open a second terminal window and enter the following command to launch a X Windows Virtual Frame Buffer:
Xvfb :99 -ac -screen 0 1280x1024x24
Then in a third terminal we’ll need to export the display:
export DISPLAY=:99
Once you’ve done that, keep the third terminal open (and all the other ones too), and you are set to run some Mink tests. Below is a screenshot of what it should look like in your Linux X Windows session:
I happen to be running CentOS 6 in Oracle VirtualBox, which is my development environment.
Create a Simple PHPUnit trait File
Using similar code to what Benjamin Eberlei mentioned in his article, I created the following simple PHPUnit trait file:
<?php // tests/AppBundle/Functional/MinkSetup.php namespace Tests\AppBundle\Functional; trait MinkSetup { private $minkBaseUrl; private $minkSession; /** * @before */ public function setupMinkSession() { $this->minkBaseUrl = 'http://192.168.0.2/app_dev.php'; //$this->minkBaseUrl = 'http://192.168.0.2' $driver = new \Behat\Mink\Driver\Selenium2Driver('firefox'); $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); } public function login($user, $pass){ $this->minkSession->visit($this->minkBaseUrl . '/login'); // Login link. $page = $this->getCurrentPage(); $page->fillField('username', $user); // Enter username. $page->fillField('password', $pass); // Enter password. $page->pressButton('_submit'); $content = $this->getCurrentPageContent(); $this->assertContains('logout', $content); // Check that 'logout' exists. } /** * @afterClass */ public function logout(){ $page = $this->getCurrentPage(); $page->clickLink('logout'); } }
The differences between Benjamin’s file and mine are:
- Uses Selenium2Driver
- Mink base URL is set directly in the trait file, not the PHPUnit dist xml file.
- I added a login() function, which I use in all my tests to authenticate.
- There is also a @afterClass annotation logout() method that gets called after each test.
Then after we create this file, we can use it in any of our functional test case files.
Creating a Simple Functional Test Case
The following code uses the above trait file and has a simple function to login and get some data and make assertions. It is a good idea at first to perform a very simple test to first verify that everything is working correctly.
<?php // tests/AppBundle/Functional/MinkPetitionTest.php namespace Tests\AppBundle\Functional; use PHPUnit\Framework\TestCase; class MinkPetitionTest extends TestCase { use MinkSetup; public function testSubmitPage(){ $this->login('some_user', 'myPassword'); // Login first. $this->visit('/submitPetStuSearch'); // Go to submit search $page = $this->getCurrentPage(); // Get the page. $page->fillField('form_ban_id', '1234'); $page->pressButton('form_find_student'); $content = $this->getCurrentPageContent(); // Get page content. $this->assertContains('<u>No Petitions</u> exist for Some User Student ID: 1234', $content); } }
Once you’ve run the simple test case, then you can continue to modify your file and add more test cases/assertions as needed.