定制 sizuhiko/spec-php 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

sizuhiko/spec-php

Composer 安装命令:

composer require sizuhiko/spec-php

包简介

This is forked Spec-PHP, and support RSpec2 syntaxs, composer.

README 文档

README

Spec for PHP is a tool to implement Behaviour-Driven Development specification files. It's inspired on RSpec from the Ruby world.

It builds on top of PHPUnit and Hamcrest projects to offer mature and solid functionality and borrow the current industry support for those projects.

The intent when implementing Spec was to mix normal PHP code and a more natural language syntax to express expectations. Writing the test code in pure PHP is great because that is how you are going to use it in your application and IDE's offer autocompletion for it. However, assertions are difficult to express and difficult to read with PHP's syntax, thus it makes sense to write them differently.

To be able to parse Spec's syntax there is an on the fly transformation that generates valid PHP code. Code generation has its drawbacks, specially when there is a need to debug a problem, the source file and the executed one are different so it becomes a nighmare to know what's going on. Spec takes this into account and will try as hard as possible to generate code that keeps the original line numbers the same. This is of great help since you can go to the line number reported in an exception and actually see the statement that failed. Check the "How does it work?" section for more details.

Check the documentation for further details.

Features

Spec for PHP is being actively developed and while functional doesn't have all of its features implemented. As thus it should be considered alpha quality software for the time being.

Working features

  • Describe and It block parsers
  • Natural language expectations parser
  • Coordinated expectations (and, or, but)
  • Before and After blocks
  • Run expectations against collections/arrays (all, any, none)
  • Parametrized It blocks
  • Annotations support (@group, @skip, @todo, @throw, ...)
  • Custom CLI runner tool
  • PHPUnit integration
  • Use annotation to inherit from custom PHPUnit_TestCase class (ie: Zend_Test)
  • Matcher factory to create matchers with a callback function
  • Any RSpec2 features (subject, its)

Upcoming

  • Review configurable options and extension points

Later

  • Additional matchers
  • Better descriptions for expectation failures
  • Port features from RSpec 2
  • First class integration of Mock frameworks (PHPUnit, Mockery, ...)

Requirements

  • PHP 5.3
  • Composer

Installation

Using composer

Add the library to your project's composer.json - something like this:

{
    "require": {
        "sizuhiko/spec-php": "0.9.*"
    }
}

Or, Add the following to your composer.json from CLI:

composer require sizuhiko/spec-php:0.9.*

To do a test run, simply checkout the repository to get the tests directory and run the following commands:

cd tests/
phpunit AllTests.php

Also try the custom cli runner:

spec4php tests

Example

<?php
// Implements the StackTest example from PHPUnit manual as a spec file
describe "Testing array operations with Spec"

    it "should support Push and Pop"

        $stack = array();
        count($stack) should equal 0;

        array_push($stack, 'foo');
        $stack[count($stack)-1] SHOULD == 'foo';
        count($stack) SHOULD BE 1;

        array_pop($stack)
        Should be "foo"

        count($stack)
            should be equal to 0
    end
end

That's it, really, no ->assert calls and no classes, methods or other verbose statements just to fit the code in.

The syntax for blocks is borrowed from RSpec, describe groups tests and it defines a block of code used to execute a test for specific functionality.

Note though that this example uses the most natural language syntax possible with Spec. It could also be writen with closures or using dots instead of spaces to separate statements, so that it becomes completely valid PHP syntax. Check the following example:

<?php
describe. "Block without closure".
    it("should multiply", function(){
        (2*2) . should.equal(4);
    });
end;

If you still preffer how a traditional PHPUnit test case looks, you might still find this library useful, have a look on the section about PHPUnit compatibility.

How does it work?

The parser for the custom syntax uses PHP's own tokenizer (token_get_all) to ensure it doesn't choke on weird statements. When it reaches a block level keyword like describe it wraps the contents in a closure function.

The keyword should uses a different parsing logic. The statement just before it is captured as the "value" or "subject" while statemens after it are captured as the "expectation" or "predicate". It's even able to parse complex expressions if they are wrapped in parenthesis.

To fool the PHP interpreter so that it receives the transformed code instead of the original Spec syntax, a custom stream wrapper is used to perform the transformation. Every file using the spec://path/to/file.php notation will be run thru Spec's parser to transform it if needed.

In order to make some sense of the expectations, the Expect class applies some simple algorithms like removing common words or managing sentence combinators like and. Take for example the following sentence:

5 should be an integer and less than 10

would be processed as if it was:

expect(5)->integer()->and_less(10);

Compatibility with PHPUnit

One of the design principles when developing Spec was to make it compatible with PHPUnit, since it's the current standard tool for testing in the PHP world.

Spec files are transformed on the fly to be compatible with PHPUnit, allowing to use its reporting (code coverage, xunit, tap logs) and current integrations with IDEs and Continuous integration services.

Feeding a \DrSlump\Spec\TestSuite object to PHPUnit it will be able to execute any spec files it references. For example, by creating the following class it will run recursively all the spec files found beneath the directory where the class is defined.

require_once 'Spec.php';

class AllSpecs extends \DrSlump\Spec\DirectoryRunnerHelper {
    static function suite() {
        return parent::suite();
    }
}

If you already have an extended TestCase class with custom assertions and helper methods, you can make use of it with Spec by using the class annotation. Spec will use the given class as base when generating the tests. This allows to make use of current PHPUnit extensions like Zend_Test from Zend Framework for example.

# class My_TestCase
describe "My Test" {
  it "should access a method of My_TestCase"
    $this->myMethod();
  end
}

It's even possible to use the expect component in PHPUnit's native test cases.

class ExpectTest extends PHPUnit_Framework_TestCase {
    function testEqual(){
        expect(1)->to_equal(1);
    }
}

Beyond Testing

The Expect component is not really tied to PHPUnit or the test harness. It's primary dependency is the Hamcrest set of matchers, as such, it can also be used in other scenarios, like for example to validate parameters received in an application controller.

See the following Zend Framework controller for example:

class MyController extends Zend_Controller_Action {
    public function myAction() {
        expect($this->getParam('id'))
        ->to_be_numeric->and_more_than(0)
        ->do();

        expect($this->getParam('action'))
        ->to_equal('create')->or('update')->or('delete')
        ->as('Invalid action')
        ->do();

        // ... your logic goes here ...
    }
}

When an expectation fails an exception is raised so it fits well with most web frameworks that capture exceptions to render an error page. Of course, the real power comes by writing custom matchers, like an user exists that checks if an user id is valid for example.

LICENSE

The MIT License

Copyright (c) 2011 Iván -DrSlump- Montes

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

sizuhiko/spec-php 适用场景与选型建议

sizuhiko/spec-php 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 15.89k 次下载、GitHub Stars 达 3, 最近一次更新时间为 2014 年 02 月 14 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「BDD」 「test」 「spec」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 sizuhiko/spec-php 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 sizuhiko/spec-php 我们能提供哪些服务?
定制开发 / 二次开发

基于 sizuhiko/spec-php 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 15.89k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 3
  • 点击次数: 1
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 3
  • Watchers: 1
  • Forks: 6
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2014-02-14