Functional Testing


Before reading this section, it is recommended that you read the Selenium documentation and the PHPUnit documentation first. We summarize in the following the basic principles of writing a functional test in Yii:

  • Like unit test, a functional test is written in terms of a class XyzTest which extends from [CWebTestCase], where Xyz stands for the class being tested. Because PHPUnit_Extensions_SeleniumTestCase is the ancestor class for [CWebTestCase], we can use all methods inherited from this class.

  • The functional test class is saved in a PHP file named as XyzTest.php. By convention, the functional test file may be stored under the directory protected/tests/functional.

  • The test class mainly contains a set of test methods named as testAbc, where Abc is often the name of a feature to be tested. For example, to test the user login feature, we can have a test method named as testLogin.

  • A test method usually contains a sequence of statements that would issue commands to Selenium RC to interact with the Web application being tested. It also contains assertion statements to verify that the Web application responds as expected.

Before we describe how to write a functional test, let's take a look at the WebTestCase.php file generated by the yiic webapp command. This file defines WebTestCase that may serve as the base class for all functional test classes.

[php]
define('TEST_BASE_URL','http://localhost/yii/demos/blog/index-test.php/');

class WebTestCase extends CWebTestCase
{
	/**
	 * Sets up before each test method runs.
	 * This mainly sets the base URL for the test application.
	 */
	protected function setUp()
	{
		parent::setUp();
		$this->setBrowserUrl(TEST_BASE_URL);
	}

	......
}

The class WebTestCase mainly sets the base URL of the pages to be tested. Later in test methods, we can use relative URLs to specify which pages to be tested.

We should also pay attention that in the base test URL, we use index-test.php as the entry script instead of index.php. The only difference between index-test.php and index.php is that the former uses test.php as the application configuration file while the latter main.php.

We now describe how to test the feature about showing a post in the blog demo. We first write the test class as follows, noting that the test class extends from the base class we just described:

[php]
class PostTest extends WebTestCase
{
	public $fixtures=array(
		'posts'=>'Post',
	);

	public function testShow()
	{
		$this->open('post/1');
	    // verify the sample post title exists
	    $this->assertTextPresent($this->posts['sample1']['title']);
	    // verify comment form exists
	    $this->assertTextPresent('Leave a Comment');
	}

	......
}

Like writing a unit test class, we declare the fixtures to be used by this test. Here we indicate that the Post fixture should be used. In the testShow test method, we first instruct Selenium RC to open the URL post/1. Note that this is a relative URL, and the complete URL is formed by appending it to the base URL we set in the base class (i.e. http://localhost/yii/demos/blog/index-test.php/post/1). We then verify that we can find the title of the sample1 post can be found in the current Web page. And we also verify that the page contains the text Leave a Comment.

Tip: Before running functional tests, the Selenium-RC server must be started. This can be done by executing the command java -jar selenium-server.jar under your Selenium server installation directory.