打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Continuous testing in PHP with Eclipse | Mike's Blog

If you already write test cases over your code, then continuous testing is a simple idea: Get fast feedback on your code by running your project’s unit tests very frequently. From PHP, the de facto standard testing tool is PHPUnit, so running tests usually involves typing phpunit into a terminal.

This post will show you how to set up a project with the Eclipse MakeGood plugin, which is a continuous test runner for the Eclipse IDE. When it is enabled, the plugin runs a set of tests every time you save a file.

This is best used on projects which are:

  • Small — so you tests run in a reasonable timeframe.
  • Complex — reasonably high risk of introducing defects.
  • Well-tested — so your unit tests are reasonably likely to identify defects.

Set up your machine

Your machine needs Eclipse PDT, MakeGood and composer.

Eclipse PDT

If you’ve found this post via Google, then you probably already run Eclipse and PHP. If not, fetch the “Eclipse for PHP developers” distribution from here

You need to pick up the XDebug extension to really make use of this setup. On Debian-based distributions, this is achieved via:

sudo apt-get install php5-xdebug

If you don’t use Eclipse yet, then check whether languages or tools you’ve used before have plugins in the Eclipse Marketplace. There’s a good chance that Eclipse will do the whole lot.

MakeGood

MakeGood is simply an Eclipse plugin, so you can fetch it from the Eclipse Marketplace.

Navigate to Help → Eclipse Marketplace and search for “makegood”:

Wait for the info to be fetched:

Check all the boxes, and then click Confirm:

Accept the terms, and wait for the install:

At one point, you will be prompted to accept a developer’s certificate, which you need to do before continuing:

This feature will not work unless you have a PHP binary set up. You need to configure this under Window → Preferences → PHP → PHP executables.:

This is system dependent: Windows users will find a file somewhere called php-cli.exe, while Linux users might find it at /usr/bin/php.

After this, MakeGood is installed. It is configured per-project, so we’ll get to that after the next section.

Composer

Composer is a dependency manager which is widely used in the PHP world.

You can get it from https://getcomposer.org/download/

Rather than use the install process which is suggested there, you can simply download the phar, make it executable, and place it somewhere like /usr/bin:

wget https://getcomposer.org/composer.pharchmod +x composer.pharsudo mv composer.phar /usr/bin/composercomposer --version

By using composer to load PHPUnit, MakeGood becomes much easier to configure.

Project setup

To start, make a new PHP project by clicking File → New → PHP Project. Name it something like “Example”.

We are using composer here because it provides an easy way to make sure MakeGood can see the PHPUnit code. So let’s set a few things up:

First, add a composer.json file which adds a recent version of PHPUnit as a require-dev dependency. Right-click Example project, and navigate to New → File, naming it composer.json:

{    "require-dev": {        "phpunit/phpunit": "4.5.*"    }}

Note that with the way that MakeGood constructs its command-line, newer versions of PHPUnit do not appear to work correctly at the time of writing.

Next up, install the new dependency with the help of Composer:

$ composer installLoading composer repositories with package informationInstalling dependencies (including require-dev)  - Installing sebastian/version (1.0.6)  - Installing sebastian/global-state (1.0.0)  - Installing sebastian/recursion-context (1.0.1)  - Installing sebastian/exporter (1.2.1)  - Installing sebastian/environment (1.3.2)  - Installing sebastian/diff (1.3.0)  - Installing sebastian/comparator (1.2.0)  - Installing symfony/yaml (v2.7.3)  - Installing doctrine/instantiator (1.0.5)  - Installing phpdocumentor/reflection-docblock (2.0.4)  - Installing phpspec/prophecy (v1.4.1)  - Installing phpunit/php-text-template (1.2.1)  - Installing phpunit/phpunit-mock-objects (2.3.6)  - Installing phpunit/php-timer (1.0.7)  - Installing phpunit/php-token-stream (1.4.3)  - Installing phpunit/php-file-iterator (1.3.4)  - Installing phpunit/php-code-coverage (2.2.2)  - Installing phpunit/phpunit (4.5.1)sebastian/global-state suggests installing ext-uopz (*)phpdocumentor/reflection-docblock suggests installing dflydev/markdown (~1.0)phpdocumentor/reflection-docblock suggests installing erusev/parsedown (~1.0)phpunit/phpunit suggests installing phpunit/php-invoker (~1.1)Writing lock fileGenerating autoload files

Set up an Example.php class with a bit of code:

<?php/** * Example of some code that could do with test cases */class Example {	/**	 * Faulty palindrome checker. A palindrome is a word which is the same when read orward and backward.	 * 	 * @param string $str	 * @return boolean True if $str is a palindrome, false if it is not.	 */	function isPalindrone($str) {		$halfLen = (int)(strlen($str) / 2);		for($i = 0; $i < $halfLen; $i++) {			// Compare characters from the front and back of the string, and move toward the middle.			$c1 = substr($str, $i, 1);			$c2 = substr($str, (2 * $halfLen - 1) - $i, 1);			if($c1 != $c2) {				return false;			}		}				return true;	}}

Set up a test/unit folder and create a ExampleTest class with a useful test case in it, like so:

<?phpclass ExampleTest extends PHPUnit_Framework_TestCase {	public function testIsPalindrome() {		$e = new Example();		$this -> assertTrue($e -> isPalindrone(""));		$this -> assertTrue($e -> isPalindrone("a"));		$this -> assertTrue($e -> isPalindrone("ABBA"));		$this -> assertFalse($e -> isPalindrone("test"));	}}

The unit tests go in their own folder, in case you decide to add more extensive (slower) tests later. MakeGood should only be configured to run fast tests!

Now add a test/bootstrap.php for test cases to load classes (NB: At scale, you would have composer autoload your classes, and use that as your PHPUnit class loader).

<?phprequire_once 'vendor/autoload.php';require_once 'Example.php';

Optionally, also add a phpunit.xml file in your project root to configure PHPUnit with, so that you can run it on the command-line:

<phpunit         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.5/phpunit.xsd"         bootstrap="test/bootstrap.php"></phpunit>

If all goes to plan, your project should look something like this:

- Continuous testing example  |- (.. code ..)  |- Example.php  |- test/  |  |- (.. other types of tests ..)   |  |- unit/  |  | |- ExampleTest.php  |  |- bootstrap.php  |- vendor  |  |- (.. dependencies ..)  |  |- autoload.php  |- composer.json  |- phpunit.xml

And more to the point, you should be able to use PHPUnit on the command-line to run the test case. It will look something like this:

Example$ php vendor/bin/phpunit test/unit/PHPUnit 4.7.7 by Sebastian Bergmann and contributors..Time: 71 ms, Memory: 4.50MbOK (1 test, 4 assertions)

Configure MakeGood

Now that the project is coming along nicely, it’s time to configure MakeGood to run the test automatically from within Eclipse.

Go to Project → Properties → MakeGood, and add the path to your unit tests, along with a link to the bootstrap.php. This bootstrap file will let MakeGood load the classes to test, along with PHPUnit itself.

Now fire up the MakeGood view. If it doesn’t come up automatically, then open it via Window → Show View → Other. Clicking the “play” button should kick off all available tests, adn if your project structure is correct, then everything will work at this point:

Once you save a file, a small box will appear in the bottom-right to indicate whether the tests worked.

As you introduce changes and save them, MakeGood will flag whether the tests are passing by changing the colour of the icon.

In this case, it is green. From the small delay that is caused when running the tests, you can see why it’s important to keep unit tests fast if you use this tool.

A test-driven bugfix cycle

Of course, Linus’ Law suggests that any code will probably have more bugs. So, say somebody reports that the palindrome “abcdedcba” is causing incorrect results. In test-driven development, you would expose this as a test case over the isPalindrome() function:

<php...		public function testIsPalindromeOddLength() {		$e = new Example();		$this -> assertTrue($e -> isPalindrone("abcdedcba"));		$this -> assertFalse($e -> isPalindrone("abc"));	}...

As soon as this is submitted, things start to turn red in MakeGood. In response to the broken test, you can then tweak the code.

You would then do the smallest amount of programming needed to pass all the tests. A palindrome checker which does not contain intentional bugs is as simple as this one-liner:

<php//...	function isPalindrone($str) {		return $str == strrev($str);	}//...

This change causes MakeGood to report that the unit tests are all passing.

Summary

A continuous test runner adds faster feedback for tedious but well-tested code. If you have to write anything in PHP which does some real computer work, then I suggest setting up MakeGood so that you can make changes to tricky code, and have a good idea of whether it’s producing sane outputs.

As this post has touched on before, slow tests should not run each time you save the code. This is why we worked in a Unit test folder. Slower integration or functional tests can still be run via the command-line in this model. An example of a project which uses this setup is escpos-php, which is a heavily test-driven PHP driver for thermal line printers.

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
Install Zend Framework on CentOS 6 / RHEL 6 >> Centos/Redhat
composer
利用 Zend Studio 九 Run As PHPUnit Test 总结
zend framework开发环境搭建-windows
基于Jenkins实现php项目的自动化测试 打包和自动部署
PHP 单元测试工具
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服