Build PHP's YII framework and related test environment on Mac OS _php instance

Source: Internet
Author: User
Yii integrates unit and functional testing, implemented with PHPUnit and selenium. I encountered a lot of trouble in the configuration process, the record here.

Necessary Concepts
Selenium
Selenium is a well-known automated testing tool that can be used to automate test Web projects by adjusting the local browser to complete the test. Selenium is divided into the server and the client, the server uses Java development, so need a JDK, the service side at startup, will start an HTTP service, the client through the HTTP communication with the server, the server to launch a test request, the server will automatically call up the browser to complete the test. Testers are responsible for writing client-side scripts that support most of the mainstream programming languages, but in fact this is due to the powerful power of the open source community, which has developed an interface program for selenium for different languages, and the protocol between the server and the client has not been studied because it is not important.

PHPUnit
PHPUnit is a test framework and tool for the PHP language, using its framework when conducting unit tests, and using its tools for functional testing. Based on this test framework, some people have done the Selenium PHP interface program on this basis, as an extension of the phpunit exists.

How the YII framework integrates
Yii has made some simple packages for testing on the basis of phpunit. Therefore, when using Yii for testing, you need to rely on both of these.

Environment installation
Firefox
Selenium-server can identify not many browsers, it seems IE and Firefox, so on OSX first install the Firefox browser. installation browser and general software installation is not a big difference, here is not exhausted.

Jdk
Since Selenium-server is developed using Java, we need to install the JDK first, Baidu search jdk download installation. No longer a statement of exhaustion.

Selenium-server
First, install the server version of selenium. Under OSX, you can use brew to install, more convenient:

$ Brew Install Selenium-server-standalone

Since the source of the Selenium-server is on the Googleapis, it is necessary to turn over the wall in order to operate, in fact, if the wall is not turned, the other steps are more difficult.

After the installation is complete the prompt:

To has 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

It is clear here that we can start the server with the following command

$ selenium-server-p 4444

As you can see, normally selenium-server listens on port 4444, if you want to modify the port, then the corresponding yii need to modify the configuration.

PHPUnit
Detour
Personal understanding, PHPUnit is a collection of tools and frameworks, tools, tools, frameworks. From the official website of the document, PHPUnit's tool part is published in the form of Phar Package, and the framework is managed through pear. So let's take a look at these two concepts first. If you are not interested, you can skip this section.

Phar is a PHP packaging solution. That is, a PHP program or PHP site can be packaged together to distribute, even as a function module call. Therefore, PHPUnit can completely package the tool program into Phar, and when executing Phar, it is often necessary to use PHP commands.

$ 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.

Use the above command to download the PHPUnit executable file, you can see this is a Phar package

Pear is a system for PHP extension libraries because it is difficult to reuse early PHP. Compiled languages are relatively easy to reuse because of their compact and rigorous syntax. And because of the flexibility of PHP, the reuse of learning cost is relatively high, so pear put forward a programming specification and distribution system to implement PHP function reuse, it seems that pear has been replaced by composer (below). But if the old things have gone through the Detour, you may wish to write down.

Under Mac You can install pear like this:

$ 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, except that it is a PHP script that installs pear, which can be executed using PHP commands. During installation, you are 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 SP Ecified directory is also not in the include_path used Byyour scripts and you'll have problems getting any PEAR packages wo Rking. Would 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 was now at your service at/usr/bin/pear** the ' pear ' command was not cur rently in your path, so you need to** use '/usr/bin/pear ' until you had added** '/usr/bin ' to your PATH environment Varia ble.

From this tip we can learn:

Pear executable program installed in/usr/bin/pear
Pear A working directory is/usr/share/pear, this working directory needs to be added to PHP.ini, if the installer is added automatically, it will be:

* * * * * Added by go-pearinclude_path= ".:/ Usr/share/pear "; * * * *

When PHP uses require and other functions including other files, PHP actually 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 there will be a system.php in the working directory, so the following code is working:

<?php  require ' system.php ';? >


Installing with composer
Originally, PHPUnit can be installed through the pear, however, the passage of time, in the composer Big line of the era, PHPUnit also announced the full support composer, and give up pear, originally through the installation of pear is not sure. Finally forced, only on the composer (say Package management tool is really more than 10 fingers enough, in the future there is a chance to a horizontal comparison).

First install the composer, in the inverted wall state:

$ Brew update$ Brew tap josegonzalez/homebrew-php$ Brew tap homebrew/versions$ Brew Install php55-intl$ Brew Install JOSEG Onzalez/php/composer

So the composer is ready.

In the root directory of the project, create a Composer.json, write:

{"  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 based on the PHPUnit write Selenium client library, see the literature after the reference.

Then, under the project root directory, execute the

$ sudo composer install

Composer will create a vendor directory in the root directory based on this Composer.json file and download all dependencies to this directory, where Vendor/bin has phpunit executables.

Because it is a project of Yii, CD to/protected/tests directory, execute the following command to start the default sitetest.php inside the test method: (note before execution, keep the Selenium-server open state)

$ .. /.. /vendor/bin/phpunit functional/sitetest.php

You will see that Firefox automatically starts during execution and is output by the following log:

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 utility will automatically find the tests/ Phpunit.xml This configuration file and make some configuration based on this, and Yii will use the framework of phpunit and Phpunit-selenium to communicate with the Selenium-server side, the server will start the browser, and the logs and results are returned to the client. The whole process is roughly the same.

Test

Testing is an essential part of software development. Whether or not we realize that we are always testing when we develop Web applications. For example, when we write a class in PHP, we may use some injection of echo or die 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 confirm that the page is interacting with our expectations. More advanced developers will write code to automate the testing process, so that whenever we need to test something, We just need to call the code, and the rest will be given to the computer. This is called automated testing and is the main topic of this chapter.

The test support provided by YII includes unit testing and functional testing.

Unit tests verify that a separate unit of code works as expected. In object-oriented programming, the most basic code unit is the class. Therefore, the primary responsibility of unit testing is to verify that every method that is implemented by this class is working correctly. Unit tests are usually written by the person who developed the class.

Functional tests verify that the feature works as expected (e.g., commit operations in a blog system). Functional testing is often more advanced than unit tests because the features to be tested often involve multiple classes. Functional testing is usually written by people who are very knowledgeable about the needs of the system. (This person can be either a developer or a quality engineer).

Test-driven development

The development cycle of the so-called test-driven Development (TDD) is shown below:

    • Create a new test that covers the attributes you want to implement. The test is expected to fail at the first execution because the feature has not yet been implemented.
    • Perform all tests to ensure that the new test is unsuccessful.
    • Write code to make the test pass.
    • Perform all tests to ensure all tests pass.
    • Refactor the newly written code and make sure that the tests are still able to pass.
    • Repeat steps 1 through 5 to promote the implementation of the overall function.

Build a test environment

The test support provided by YII requires PHPUnit 3.5+ and Selenium remote control 1.0+. Please refer to the documentation they provide 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
The tests/contains application testing
Fixtures/contains the data fixtures
The functional/contains functional tests
The unit/contains unit tests
The report/contains coverage reports
bootstrap.php This script executes at the beginning
Phpunit.xml phpunit configuration file
webtestcase.php Web-based functional test base class
As shown above, our test code is mainly in the three directories of fixtures, functional and unit, and the report directory is used to store generated code coverage reports.

We can execute the test (either unit or functional) in the console window by executing the following command:

% CD testdrive/protected/tests% phpunit functional/posttest.php  //Perform single test% phpunit--verbose functional    //execute ' All tests under functional '% phpunit--coverage-html./report Unit

The last command above executes all the tests under the Unit directory and generates a code-coverage report in the reports directory. Note to generate the Code-coverage report you must install and open the PHP xdebug extension.

Test the boot script

Let's take a look at what's going on in the bootstrap.php file. First of all, this file is a bit special, because it looks like a portal script, and it's the entrance to a series of tests that we perform.

$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.php file from the YII framework, which initializes some global constants and the necessary test base classes. Then we use the test.php configuration file to create an application instance. If you look at the test.php file, you will find it is inherited from Mai n.php This configuration file, except that it adds a fixture application component with the class name [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 (  ' connectionString ' = ' DSN for test database ',  ),  */),));
When I perform tests that involve database operations, we should provide a test-specific database so that test execution does not interfere with normal development or production activities. In this way, we need to remove the comments from the DB configuration above, and then fill in the DSN (data source name) of the connectionString attribute to connect to the database.

With such a startup script, when we perform unit tests, we can get an application instance that is similar to the requirements of the service, and the main difference is that the test has a fixture manager and its own test database.

Define a specific state (fixtures)

Automated tests need to be executed many times. To ensure that the testing process is repeatable, we want to test it in some known state, which we call a specific state. For example, in a blog app, test the article creation feature, each time we test, the table related to the article (for example. The Post table, Comment table) should be restored to a specific state. The PHPUnit documentation is a good description of the general construction of a particular state. This section focuses on how to build a database-specific state like the example just described.

Setting the specific state of the build database is probably one of the most time-consuming parts of testing an application with a database for back-end support. The [Cbbfixturemanager] application component introduced by YII can alleviate this problem effectively. When a set of tests is carried out, it basically does the following things:

It resets the test-related data to a known state before all tests are run.
Before a single test runs, it resets the specific table to the known state.
During the execution of a test method, it provides the provider of the row data that is supplied to a particular state.
Please use the [Cdbfixturemanager] that we configured in the application configuration as follows.

Return Array (' Components ' =>array (' fixture ' =>array ('  class ' = ' System.test.CDbFixtureManager ',),);

We then provide a specific status data under directory Protected/tests/fixtures. This directory can be specified as a different directory by configuring the [Cdbfixturemanager::basepath] property in the app configuration file. Specific state data is a combination of multiple PHP files called a specific state file. Returns an array for each specific state file. Represents the initial row for a particular table of data. The file name and table name are the same. The following is the example of storing the specific state data of the Post table in a file named post.php.

<?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, there are two rows of data returned. Each row represents an array whose key is the field name of the table, and its value is the corresponding field value. The index of each row is a string called the row alias (for example: Simple1, Simple2). Later, when we write the test script, we can easily invoke this line of data through its alias. You may have noticed that we did not specify the value of the ID field in the specific state described above. This is because the ID field has been defined as the self-increment primary key, and its value is automatically generated when we insert new data.

When [Cdbfixturemanager] is referenced for the first time, it examines all of the specific state files and then uses them to reset the corresponding table. It resets the table by emptying the table, resetting the value of the table primary Key's self-increment sequence, and then inserting the data rows from the specific state file into the table.

Sometimes, we may not want to reset each table described in a particular state file before a set of tests, because it can take a lot of time to reset too many specific state files. In this case, we can write a PHP script to customize this initialization process. This should be stored in a directory that holds a specific state file. and named Init.php. When [Cdbfixturemanager] detects the existence of this script, it executes the script instead of resetting each table.

It is also possible not to use the default method to reset the table, for example, emptying the table and inserting specific state data. If this is the case, we can write an initialization script for the specified state file. This script must have a name of table name +.init.php. For example, the init script file for the Post table is Post.init.php. When [Cdbfixturemanager] finds the script, it executes the 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 those tables in the test where the data will change. The tables that you do as lookup services do not change, so you do not need a specific state file.

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.