This article mainly introduces how to build the Yii framework of PHP and related testing environment on MacOS. Mac comes with software such as Apache and PHP, so it is very comfortable to build a development environment, for more information about how to use phpunit and selenium, see YII integration of unit test and function test. I encountered a lot of trouble in the configuration process, which is recorded here.
Concepts
Selenium
Selenium is a well-known automated testing tool. It can be used to automatically test web projects by starting a local browser. Selenium is divided into two types: server and client. The server uses java for development. Therefore, a jdk is required. When the server is started, an http service is started, and the client performs http Communication with the server, when a test request is sent to the server, the server automatically calls the browser to complete the test. The tester is responsible for compiling client scripts and supporting most mainstream programming languages. Of course, this is because of the powerful power of the open-source community. It is only necessary to develop an interface program for selenium for different languages, the protocol between the server and the client is not studied by the author, because this is not important.
Phpunit
Phpunit is a php testing framework and tool. It is used for unit testing and used for functional testing. Based on this test framework, some people have developed the selenium php interface program on this basis as an extension of phpunit.
How to integrate the YII framework
Yii has made some simple encapsulation for the Test Based on phpunit. Therefore, Yii is required for testing.
Environment Installation
Firefox
There are not many browsers that selenium-server can recognize. They seem to be IE and Firefox, so install the Firefox browser on OSX first. There is no major difference between browser installation and general software installation.
JDK
Because selenium-server is developed in java, We need to install JDK first, and download and install JDK by Baidu search. No more details.
Selenium-server
First install the server version of selenium. In osx, brew can be used for installation, which is more convenient:
$ brew install selenium-server-standalone
Because the selenium-server Source is on googleapis, You need to flip the wall to perform operations. In fact, if you do not flip the wall, other steps are also difficult.
After the installation is complete, the following message is displayed:
To have launchd start selenium-server-standalone at login: ln -sfv /usr/local/opt/selenium-server-standalone/*.plist ~/Library/LaunchAgentsThen to load selenium-server-standalone now: launchctl load ~/Library/LaunchAgents/homebrew.mxcl.selenium-server-standalone.plistOr, if you don't want/need launchctl, you can just run: selenium-server -p 4444
The following command is used to start the server:
$ selenium-server -p 4444
As you can see, selenium-server listens to port 4444. If you want to modify the port, You need to modify the configuration at the corresponding Yii.
Phpunit
Detour
In my personal understanding, phpunit is a collection of tools and frameworks. Tools are classified into tools and frameworks. The phpunit tool is released in the form of a phar package, and the framework is managed by pear. Record these two concepts first. Skip this section if you are not interested.
Phar is a php packaging solution. That is, a php program or php website can be packaged and distributed together, and even called as a function module. Therefore, phpunit can completely package the tool program into phar. When executing phar, php commands are usually required.
$ wget https://phar.phpunit.de/phpunit.phar$ chmod +x phpunit.phar$ sudo mv phpunit.phar /usr/local/bin/phpunit$ phpunit --versionPHPUnit x.y.z by Sebastian Bergmann and contributors.
You can use the above command to download the executable file of phpunit. You can see that this is a phar package.
Pear is a php extension library system, because it is difficult to reuse php in the early stage. Compilation languages are easier to reuse because of their compact and rigorous syntax. Due to the flexibility and variety of php, the learning cost for reuse is relatively high. Therefore, pear proposed a programming specification and distribution system to reuse php functions, now it seems that pear has been replaced by composer (as described below ). However, since the old things have already taken a detour, you may wish to write it down.
You can install pear in mac as follows:
$ wget http://pear.php.net/go-pear.phar$ sudo php -d detect_unicode=0 go-pear.phar
As you can see, go-pear is also a phar, but it is a php script for installing pear. It can be executed using the php Command. During installation, you will be prompted to modify the php. ini file:
WARNING! The include_path defined in the currently used php.ini does notcontain the PEAR PHP directory you just specified:If the specified directory is also not in the include_path used byyour scripts, you will have problems getting any PEAR packages working.Would you like to alter php.ini ? [Y/n] : Yphp.ini include_path updated.Current include path : .:Configured directory : /usr/share/pearCurrently used php.ini (guess) : /etc/php.iniPress Enter to continue: The 'pear' command is now at your service at /usr/bin/pear** The 'pear' command is not currently in your PATH, so you need to** use '/usr/bin/pear' until you have added** '/usr/bin' to your PATH environment variable.
We can learn from this prompt:
The executable program of pear is installed in/usr/bin/pear.
Pear has a working directory:/usr/share/pear. This working directory needs to be added to php. ini. If you want the installation program to be automatically added, it will be like this:
;***** Added by go-pearinclude_path=".:/usr/share/pear";*****
When we use functions such as require in php that contain other files, php searches for include_path in addition to the current directory. This configuration indicates that the program code installed through pear will be stored in the working directory, and php can be found. By default, a System will exist in the working directory. php, so the following code can work:
<?php require 'System.php';?>
Install with composer
Originally, phpunit can be installed through pear. However, in the era of composer, phpunit also announced full support for composer and gave up pear, the installation method through pear was not working. Finally, we had to go to composer. (The package management tool is not enough to use more than 10 fingers. In the future, we will have the opportunity to make a horizontal comparison ).
First, install composer:
$ brew update$ brew tap josegonzalez/homebrew-php$ brew tap homebrew/versions$ brew install php55-intl$ brew install josegonzalez/php/composer
In this way, composer is installed.
Under the root directory of the project, create a composer. json file and write it:
{ "require-dev": { "phpunit/phpunit": "4.7.*", "phpunit/php-invoker": "*", "phpunit/dbunit": ">=1.2", "phpunit/phpunit-selenium": ">=1.2", "phpunit/phpunit-story": "*" }}
The above phpunit-selenium is the selenium client library written based on phpunit. For details, refer to the reference documents below.
Run
$ sudo composer install
Composer will create a vender directory in the root directory based on the composer. json file, and download all the dependent items to this directory. There is a phpunit executable file under the vender/bin.
Because it is a Yii project, cd to the/protected/tests directory, execute the following command to start the default SiteTest. test method in php: (Note that selenium-server is enabled before execution)
$ ../../vendor/bin/phpunit functional/SiteTest.php
Firefox is automatically started during execution and is output by the following logs:
PHPUnit 4.7.7 by Sebastian Bergmann and contributors.Warning: Deprecated configuration setting "selenium" used.Time: 11.52 seconds, Memory: 6.50MbOK (1 test, 1 assertion)
The phpunit tool automatically finds tests/phpunit. the xml configuration file carries out some configuration based on this. Yii uses the phpunit and phpunit-selenium frameworks to communicate with selenium-server, and the server starts the browser, and return logs and results to the client. The entire process is roughly like this.
Test
Testing is an essential part of software development. whether or not we realize that we are always testing Web applications during development. for example, when we use PHP to write a class, we may use some echo or die injection statements to show whether we have implemented a method correctly; when we implement a web page that contains a complex set of HTML forms, we may try to enter some test data to check whether the page interacts as expected. more advanced developers will write some code to automatically complete the test process, so that whenever we need to test something, we only need to call the code, and the rest will be handed over to the computer. this is the so-called automatic testing, which is also the main topic of this chapter.
Yii provides testing support including unit testing and functional testing.
Unit testing checks whether an independent unit of the code works as expected. in object-oriented programming, the most basic code unit is class. therefore, the main responsibility of unit testing is to verify that every method implemented by this class works normally. unit Tests are usually written by people who develop this class.
The function test checks whether the features work as expected (for example, submitting operations in a blog system ). compared with unit testing, functional testing is generally more advanced, because the features to be tested often involve multiple classes. functional testing is usually written by people who have a good understanding of system requirements. (this person can be either a developer or a quality engineer ).
Test-driven development
The following shows the development cycle of the so-called test-driven development (TDD:
- Create a new test that covers the features to be implemented. The test is expected to fail during the first execution because the feature has not yet been implemented.
- Execute all tests to make sure the new test fails.
- Write code to make the test pass.
- Execute all tests to make sure all tests pass.
- Refactor the newly written code and make sure these tests still pass.
- Repeat steps 1 to 5 to implement the overall function.
Build a test environment
The test support provided by Yii requires PHPUnit 3.5 + and Selenium Remote Control 1.0 +. Refer to their documentation to install PHPUnit and Selenium Remote Control.
When we use the yiic webapp console command to create a new Yii application, it will generate the following files and directories for us to write and complete the test.
Testdrive/
Protected/contains protected Application Files
Tests/includes application testing
Fixtures/contains data fixtures
Functional/Includes function tests
Unit/Includes unit Tests
Report/contains coverage report
The bootstrap. php script is executed at the beginning.
Phpunit. xml PHPUnit configuration file
WebTestCase. php Web-based functional testing base class
As shown above, our test code is mainly stored in the fixtures, functional, and unit directories. The report directory is used to store the generated code coverage report.
You can run the following command in the console to perform the test (unit test or function test ):
% Cd testdrive/protected/tests % phpunit functional/PostTest. php // execute a single test % phpunit -- verbose functional // execute all the tests under 'functional' % phpunit -- coverage-html. /report unit
The last command above will execute all tests under the unit directory and generate a code-coverage report under the report directory. note that to generate a code-coverage report, you must install and enable the xdebug extension of PHP.
Pilot script for testing
Let's take a look at what will happen in the bootstrap. php file. First, this file is a bit special, because it looks like an entry script, and it is also the entry for executing a series of tests.
$yiit='path/to/yii/framework/yiit.php';$config=dirname(__FILE__).'/../config/test.php';require_once($yiit);require_once(dirname(__FILE__).'/WebTestCase.php');Yii::createWebApplication($config);
As shown above, we first include the yiit from the Yii framework. php file, which initializes some global constants and necessary test base classes. then we use test. php configuration file to create an application instance. if you view test. php file, you will find that it is inherited from main. php configuration file, but it adds a fixture application component named [CDbFixtureManager.
Return CMap: mergeArray (require (dirname (_ FILE __). '/main. php '), array ('components' => array ('fixture' => array ('class' => 'System. test. CDbFixtureManager ',),/* remove the following comments to provide a database connection for the test. 'db' => array ('ononstring' => 'dsn for test database ',),*/),));
When I perform tests involving database operations, we should provide a dedicated database for testing so that the test execution will not interfere with normal development or production activities. in this way, we need to remove the comment of the above db configuration, and then fill in the DSN (Data Source Name) for the connectionString attribute to connect to the database.
With such a STARTUP script, when we perform a unit test, we can obtain an application instance that is similar to the service requirements, the main difference is that the test has a fixture manager and its exclusive test database.
Define a specific State (Fixtures)
Automatic Testing needs to be executed many times. to ensure that the test process can be repeated, we would like to perform the test in some known states. This state is called a specific State. for example, test the document creation feature in a blog application. Each time we perform a test, the table related to the document (for example. post table, Comment table) should be restored to a specific State. the PHPUnit document describes the construction of a specific State. this section describes how to build a specific database status as described in the preceding example.
Set the specific status of the database to be built. This is probably one of the most time-consuming parts of the application that uses the database as the backend support. the [CBbFixtureManager] Application Component introduced by Yii can effectively alleviate this problem. when performing a group of tests, it basically does the following:
Before all tests are run, it resets test-related data to a known state.
Before a single test is run, it resets a specific table to a known state.
During the execution of a test method, it provides an access interface to provide row data in a specific State.
Use the [CDbFixtureManager] We configured in the application configuration as follows.
return array( 'components'=>array( 'fixture'=>array( 'class'=>'system.test.CDbFixtureManager', ), ),);
Then we provide a specific status data under the directory protected/tests/fixtures. this directory can be specified as another directory by configuring the [CDbFixtureManager: basePath] attribute in the application configuration file. specific State data is composed of multiple PHP files called specific State files. each specific status file returns an array representing the initial row of a specific table of data. the file name is the same as the table name. the specific status data of the Post table is stored in Post. example in the php file.
<?phpreturn array( 'sample1'=>array( 'title'=>'test post 1', 'content'=>'test post content 1', 'createTime'=>1230952187, 'authorId'=>1, ), 'sample2'=>array( 'title'=>'test post 2', 'content'=>'test post content 2', 'createTime'=>1230952287, 'authorId'=>1, ),);
As we can see, the above two rows of data are returned. each row represents an array. Its key is the field name of the table, and its value is the corresponding field value. each row's index is a string called a row alias (for example, simple1, simple2 ). later, when writing a test script, we can easily call this line of data through its alias. you may have noticed that we have not specified the value of the id field in the above specific status. this is because the id field has been defined as the auto-increment primary key, and its value will be automatically generated when we insert new data.
When [CDbFixtureManager] is referenced for the first time, it will carefully check all the specific status files and use them to reset the corresponding table. it clears the table, resets the auto-incrementing Sequence Value of the table's primary key, and inserts data rows from a specific State file into the table to reset the table.
Sometimes, we may not want to reset each table described in a specific State file before a set of tests, because resetting too many specific State files may take a lot of time. in this case, we can write a PHP script to customize the initialization process. this script should be saved in the directory where the specified state file is stored and named init. php. when [CDbFixtureManager] detects the existence of this script, it will execute this script instead of resetting every table.
You do not like to reset the table by default. For example, you can clear the table and insert data in the specified status. in this case, we can write an initialization script for the specified state file. this script must be named table name +. init. php. for example, the initialization script file of the Post table is Post. init. php. when [CDbFixtureManager] discovers this script, it will execute this script instead of resetting the table by default.
Tip: too many specific State files greatly extend the test time. therefore, you should only provide specific State files for tables whose data changes during the test. the tables used as search services do not change, so no specific State files are required.