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:

Mink Setup

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.