proposal for xspep bdd framework for php

Post on 13-Jan-2015

1.423 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

 

TRANSCRIPT

Proposal for xSpec BDD Framework

for PHPBeyond PHPUnit and PHPSpec

@yuya_takeyama

Recent Activities•Making DSL with [] (#phpcon2011 LT)

http://blog.yuyat.jp/archives/1355

• PHPUnit でよりよくテストを書くためにhttp://blog.yuyat.jp/archives/1386

• phpenv で複数の PHP 環境を管理するhttp://blog.yuyat.jp/archives/1446

• Building Development Environmentwith php-build and phpenvhttp://blog.yuyat.jp/archives/1461

•例えば, Singleton を避ける (New! #TddAdventJp)

http://blog.yuyat.jp/archives/1500

xSpec?

xUnit?

xUnit (Unit Testing Frameworks)

•SUnit (Smalltalk)

•JUnit (Java)•Test::Unit (Ruby)•PHPUnit (PHP)

xSpec?reprise

xSpec (Testing Frameworks for BDD)

•RSpec (Ruby)•Jasmine (JavaScript)

•specs (Scala)•PHPSpec (PHP)

BDD?

BDD (Behaviour Driven Development)

•Not test, specify!•“It should ...”•Expressive•Test as Documentation

RSpec exampledescribe Bowling do  describe '#score' do    context 'all gutter game' do      before do        @bowling = Bowling.new        20.times { @bowling.hit(0) }      end

      it 'should equal 0' do        @bowling.score.should eq(0)      end    end  endend

RSpec exampledescribe Bowling do  describe '#score' do    context 'all gutter game' do      before do        @bowling = Bowling.new        20.times { @bowling.hit(0) }      end

      it 'should equal 0' do        @bowling.score.should eq(0)      end    end  endend Not Test, Specify

RSpec exampledescribe Bowling do  describe '#score' do    context 'all gutter game' do      before do        @bowling = Bowling.new        20.times { @bowling.hit(0) }      end

      it 'should equal 0' do        @bowling.score.should eq(0)      end    end  endend “It should ...”

RSpec exampledescribe Bowling do  describe '#score' do    context 'all gutter game' do      before do        @bowling = Bowling.new        20.times { @bowling.hit(0) }      end

      it 'should equal 0' do        @bowling.score.should eq(0)      end    end  endend Expressive

RSpec exampledescribe Bowling do  describe '#score' do    context 'all gutter game' do      before do        @bowling = Bowling.new        20.times { @bowling.hit(0) }      end

      it 'should equal 0' do        @bowling.score.should eq(0)      end    end  endend

Test as Documentation

I ❤RSpec

PHPUnit exampleclass BowlingTest extends PHPUnit_Framwork_TestCase{    private $_bowling;

    public function setUp()    {        $this->_bowling = new Bowling;    }

    public function testScore0ForAllGutterGame()    {        for ($i = 0; $i <= 20; $i++) {            $this->_bowling->hit(0);        }        $this->assertEquals(0, $this->_bowling->score);    }}

PHPSpec exampleclass DescribeBowling extends \PHPSpec\Context{    private $_bowling;

    public function before()    {        $this->_bowling = $this->spec(new Bowling);    }

    public function itShouldScore0ForAllGutterGame()    {        for ($i=1; $i<=20; $i++) {            $this->_bowling->hit(0);        }        $this->_bowling->score->should->equal(0);    }}

PHPSpec exampleclass DescribeBowling extends \PHPSpec\Context{    private $_bowling;

    public function before()    {        $this->_bowling = $this->spec(new Bowling);    }

    public function itShouldScore0ForAllGutterGame()    {        for ($i=1; $i<=20; $i++) {            $this->_bowling->hit(0);        }        $this->_bowling->score->should->equal(0);    }} Not Test, Specify

PHPSpec exampleclass DescribeBowling extends \PHPSpec\Context{    private $_bowling;

    public function before()    {        $this->_bowling = $this->spec(new Bowling);    }

    public function itShouldScore0ForAllGutterGame()    {        for ($i=1; $i<=20; $i++) {            $this->_bowling->hit(0);        }        $this->_bowling->score->should->equal(0);    }} “It should ...”

PHPSpec exampleclass DescribeBowling extends \PHPSpec\Context{    private $_bowling;

    public function before()    {        $this->_bowling = $this->spec(new Bowling);    }

    public function itShouldScore0ForAllGutterGame()    {        for ($i=1; $i<=20; $i++) {            $this->_bowling->hit(0);        }        $this->_bowling->score->should->equal(0);    }} Expressive

PHPSpec exampleclass DescribeBowling extends \PHPSpec\Context{    private $_bowling;

    public function before()    {        $this->_bowling = $this->spec(new Bowling);    }

    public function itShouldScore0ForAllGutterGame()    {        for ($i=1; $i<=20; $i++) {            $this->_bowling->hit(0);        }        $this->_bowling->score->should->equal(0);    }}

Test as Documentation

I ❤PHPSpec

I ❤PHPUnit

But...

Issue of PHPUnit/PHPSpec

•No nested context•Specification with camelCase or lower_case_with_underscore

Issue of PHPUnit/PHPSpec

•No nested context•Specification with camelCase or lower_case_with_underscore

I want moreexpressiveness!

Isolved

Speciphy

•Nested context•Specification with string•PHPSpec matchers

https://github.com/yuya-takeyama/Speciphy

Speciphy examplenamespace Speciphy\DSL;

return describe('Bowling', array(    describe('->score', array(        context('all gutter game', array(            'subject' => function () {                $bowling = new Bowling;                for ($i = 1; $i <= 20; $i++) {                    $bowling->hit(0);                }                return $bowling;            },

            it('should equal 0', function ($bowling) {                $bowling->score->should->equal(0);            }),        )),    )),));

Speciphy examplenamespace Speciphy\DSL;

return describe('Bowling', array(    describe('->score', array(        context('all gutter game', array(            'subject' => function () {                $bowling = new Bowling;                for ($i = 1; $i <= 20; $i++) {                    $bowling->hit(0);                }                return $bowling;            },

            it('should equal 0', function ($bowling) {                $bowling->score->should->equal(0);            }),        )),    )),));

Not Test, Specify

Speciphy examplenamespace Speciphy\DSL;

return describe('Bowling', array(    describe('->score', array(        context('all gutter game', array(            'subject' => function () {                $bowling = new Bowling;                for ($i = 1; $i <= 20; $i++) {                    $bowling->hit(0);                }                return $bowling;            },

            it('should equal 0', function ($bowling) {                $bowling->score->should->equal(0);            }),        )),    )),));

“It should...”

Speciphy examplenamespace Speciphy\DSL;

return describe('Bowling', array(    describe('->score', array(        context('all gutter game', array(            'subject' => function () {                $bowling = new Bowling;                for ($i = 1; $i <= 20; $i++) {                    $bowling->hit(0);                }                return $bowling;            },

            it('should equal 0', function ($bowling) {                $bowling->score->should->equal(0);            }),        )),    )),));

Expressive

Speciphy examplenamespace Speciphy\DSL;

return describe('Bowling', array(    describe('->score', array(        context('all gutter game', array(            'subject' => function () {                $bowling = new Bowling;                for ($i = 1; $i <= 20; $i++) {                    $bowling->hit(0);                }                return $bowling;            },

            it('should equal 0', function ($bowling) {                $bowling->score->should->equal(0);            }),        )),    )),));

Test as Documentation?

Proposal #1Use functionin namespace,Not methodin class

Speciphy examplenamespace Speciphy\DSL;

return describe('Bowling', array(    describe('->score', array(        context('all gutter game', array(            'subject' => function () {                $bowling = new Bowling;                for ($i = 1; $i <= 20; $i++) {                    $bowling->hit(0);                }                return $bowling;            },

            it('should equal 0', function ($bowling) {                $bowling->score->should->equal(0);            }),        )),    )),));

\Speciphy\DSL\describe

Speciphy examplenamespace Speciphy\DSL;

return describe('Bowling', array(    describe('->score', array(        context('all gutter game', array(            'subject' => function () {                $bowling = new Bowling;                for ($i = 1; $i <= 20; $i++) {                    $bowling->hit(0);                }                return $bowling;            },

            it('should equal 0', function ($bowling) {                $bowling->score->should->equal(0);            }),        )),    )),));

\Speciphy\DSL\context

Speciphy examplenamespace Speciphy\DSL;

return describe('Bowling', array(    describe('->score', array(        context('all gutter game', array(            'subject' => function () {                $bowling = new Bowling;                for ($i = 1; $i <= 20; $i++) {                    $bowling->hit(0);                }                return $bowling;            },

            it('should equal 0', function ($bowling) {                $bowling->score->should->equal(0);            }),        )),    )),));

\Speciphy\DSL\it

Proposal #2

Use arrayto build

nested context.

Speciphy examplenamespace Speciphy\DSL;

return describe('Bowling', array(    describe('->score', array(        context('all gutter game', array(            'subject' => function () {                $bowling = new Bowling;                for ($i = 1; $i <= 20; $i++) {                    $bowling->hit(0);                }                return $bowling;            },

            it('should equal 0', function ($bowling) {                $bowling->score->should->equal(0);            }),        )),    )),));

Nested context

Array,A Strange

Data Structure

[ "foo", "bar", "hoge" => "piyo"]

array(3) { [0]=> string(3) "foo" [1]=> string(3) "bar" ["hoge"]=> string(4) "piyo"}

Likekeywordarguments

public $id = [ 'int', 'primary' => true, 'serial' => true];public $name = [ 'string', 'required' => true, 'unique' => true];public $birthday = ['date'];

Model Definition

["div",  ["ul",    ["li", "Foo"]    ["li", "Bar"]    ["li", "Baz"]]]

Pamlhttps://github.com/yuya-takeyama/php-HTML_Paml

<div>  <ul>    <li>Foo</li>    <li>Bar</li>    <li>Baz</li>  </ul></div>

HTML Generation

['begin', ['define', 'fib', ['lambda', ['x'], ['if', ['<', ':x', 2], ':x', ['+', ['fib', ['-', ':x', 2]], ['fib', ['-', ':x', 1]]]]]], ['print', 'fib(10) = '], ['println', ['fib', 10]]] => fib(10) = 55

LisPHPhttps://github.com/yuya-takeyama/LisPHP

Speciphy examplenamespace Speciphy\DSL;

return describe('Bowling', array(    describe('->score', array(        context('all gutter game', array(            'subject' => function () {                $bowling = new Bowling;                for ($i = 1; $i <= 20; $i++) {                    $bowling->hit(0);                }                return $bowling;            },

            it('should equal 0', function ($bowling) {                $bowling->score->should->equal(0);            }),        )),    )),));

$arr[‘subject’]

Speciphy examplenamespace Speciphy\DSL;

return describe('Bowling', array(    describe('->score', array(        context('all gutter game', array(            'subject' => function () {                $bowling = new Bowling;                for ($i = 1; $i <= 20; $i++) {                    $bowling->hit(0);                }                return $bowling;            },

            it('should equal 0', function ($bowling) {                $bowling->score->should->equal(0);            }),        )),    )),));

$arr[0]

Conclusion•Use function in namespace,Not method in class

•Use array to build nested structure

•Enjoy BDD with xSpec

Questions?or

Claims?

top related