SlideShare a Scribd company logo
1 of 49
Download to read offline
phpspecで学ぶ
London School TDD
オープンソースカンファレンス2015 HOKKAIDO
2015.6.13
最初に告知
Sapporo.php勉強会やります
7/17(金) 19:00~21:00 インフィニットループ会議室
http://sapporophp.connpass.com/
https://github.com/sapporophp/sapporophp
こんな勉強会があったらいいなといったご意見はgithubまで
自己紹介
石田朗雄
http://iakio.hatenablog.com/
https://twitter.com/iakio
http://qiita.com/iakio
http://www.slideshare.net/iakio
Motivation
PHPの偉い人でもTDDの偉い人でもありません
あと特別英語が得意なわけでもありません
でもphpspecもLondon School TDDも日本ではあまり情報量が多くな
い(海外のPHPコミュニティでは度々話題になっている模様)
本当はこういう話を自分で話すんじゃなく誰かにしてほしい
ガチ勢から見ると突っ込みどころあるかもしれませんが出来るだ
け自分の言葉で説明したいと思います
最後に沢山参考資料へのリンクを付たよ お客様の中で
London PHPコミュ
ニティの方はい
らっしゃいますか
London school TDD
ロンドンのXPコミュニティが発祥
モックを積極的に使い、状態ではなく振る舞いに注目したTDDの
手法
Growing Object-Oriented Software Guided By Tests(2009)
通称The GOOS Book
実践テスト駆動開発(2012)
phpspecの作者「London school TDDを学ぶ上でベストなリソース」
(Full Stack Radio #15)
ただし結構難しい本
◦ GUIあり、ネットワーク通信あり、マルチスレッドあり
◦ 難しい問題を解決する手法を解説しようとすると、例も難しくなると
いう技術書のジレンマ
個人的な体験として
The GOOS Bookを読む → 「なるほど(わからん)」
phpspecを知る → 「なるほど(わからん)」
phpspecについて調べる → 「それThe GOOS Bookに書いてあるよ」
The GOOS Bookを読む → 「ホンマや!」
💡 phpspecを学ぶこ
とでLondon School
TDDが理解できた
(気がする)
phpspecを使えば
London School TDD
を上手く説明でき
るのでは?
俺は単体テストが書きたい
だけなんだ
(可能であれば)大きなプログラムより小さなプログラムの方が
テストは簡単なはず
テストが失敗した場合も原因の特定が簡単なはず
今書いたコードを今すぐ動かして確認したい
依存関係
Bが無いとAを作れない
CとDが無いとBを作れない
どのように単体テストを行うか
class A {
function __construct(B $b) {
}
}
class B {
function __construct(C $c, D $d) {
}
}
class C {
}
class D {
}
Outside-In/Inside-Out
class A {
function __construct(B $b) {
}
}
class B {
function __construct(C $c, D $d) {
}
}
class C {
}
class D {
}
Outside-In
◦ Bをダミー(Mock, Stub)に置き換え
てAをテストする
◦ AがBに要求しているものが明確にな
る
Inside-Out
◦ C,Dを先に実装してからBを実装する
◦ テストの粒度は次第に大きくなる
◦ ダミーを実装する手間はかからない
◦ Bを実装中はAが存在しないので、A
がBに何を要求するかわからない
モックを積極的に使う
あるメソッドを呼び出したとき、
最終的には値を返すか他のオブ
ジェクトのメソッドを呼び出し
ているはず
テスト対象のオブジェクトと、
関連するオブジェクトの間のや
り取りだけ確認できれば、テス
ト対象のオブジェクト内で起き
ていることは気にする必要は無
いのでは?(プライベートメ
ソッド、プライベート変数)
もう全部モックでいいんじゃな
いかな
Mock
Mock
Mock Mock
phpspec
大雑把にいえばPHPUnitのようなもの(だいぶ違う)
大雑把にいえばRSpecのようなもの(だいぶ違う)
phpspec(ver1)は2011年ごろからあった(RSpecを参考にしたも
のだったらしい)
2013年ごろ0から書き直され、2014年にver2.0.0がリリースされる
現在の最新は2.2.1
2013年以前のphpspecに関する情報は全く別のものだと思ってくだ
さい
Spec, Example
class MarkdownSpec extends ObjectBehavior
{
}
function it_is_initializable()
{
$this->shouldHaveType('Markdown');
}
function its_xxxxxx()
{
....
}
そのオブジェクト
をどのように使う
かという例を集め
たものがSpecとな
る
Example=例
どのように使うの
か、という例を書
くつもりで
デモ
ここからしばらく自分用のカンペ(あるいはスライド公開用)
{
"require-dev": {
"phpspec/phpspec": "~2.2"
},
"autoload": {
"psr-4": {
"": "src/"
}
}
}
標準構成ではソースをsrc/、スペックをspec/に
配置します。それ以外の場合や.phpspec.ymlで
設定が必要です
PSR-0でも問題ありません
composer.json
Getting Started
MarkdownをHTMLに変換するMarkdownクラスのSpecを例に説明
します
といっても"Hi, there"を"<p>Hi, there</p>"に変換するだけ
公式ドキュメントと同じサンプルですいません
C:¥Users¥ishida¥src¥phpspec>vendor¥bin¥phpspec desc Markdown
Specification for Markdown created in
C:¥Users¥ishida¥src¥phpspec¥spec¥MarkdownSpec.php.
MarkdownクラスのSpecのひな形を作成します
phpspecコマンドを使わずに作ってもよいです
<?php
namespace spec;
use PhpSpec¥ObjectBehavior;
use Prophecy¥Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('Markdown');
}
}
spec/MarkdownSpec.php
MarkdownクラスのSpecはMarkdownSpecとなり
ます。各exampleメソッドはit_又はits_から始ま
ります
C:¥Users¥ishida¥src¥phpspec>vendor¥bin¥phpspec run
Markdown
10 - it is initializable
class Markdown does not exist.
/ skipped: 0% / pending: 0% / passed: 0% / failed: 0% / broken:
100%
/ 1 examples
1 specs
1 example (1 broken)
24ms
Do you want me to create `Markdown` for you?
[Y/n]
Class Markdown created in C:¥Users¥ishida¥src¥phpspec¥src¥Markdown.php.
/ skipped: 0% / pending: 0% / passed: 100% / failed: 0% / broken: 0%
/ 1 examples
1 specs
1 example (1 passed)
50ms
スペックを実行すると、スペックの対象である
Markdownクラスが無いので作りますか?と聞
かれます
<?php
class Markdown
{
}
src/Markdown.php
空のMarkdowクラスができます
...
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_paragraph()
{
// $this->toHtml("Hi, there")が
// "<p>Hi, there</p>" を返却すること
}
}
spec/MarkdownSpec.php
...
class MarkdownSpec extends ObjectBehavior
{
function it_converts_plain_text_to_paragraph()
{
$this->toHtml("Hi, there")
->shouldReturn("<p>Hi, there</p>");
}
}
spec/MarkdownSpec.php
shouldBe, shouldBeEqualTo, shouldEqualToとも書
けます
C:¥Users¥ishida¥src¥phpspec>vendor¥bin¥phpspec run
/ skipped: 0% / pending: 0% / passed: 100% / failed: 0% / broken: 0%
Markdown
15 - it converts plain text to paragraph
method Markdown::toHtml not found.
/ skipped: 0% / pending: 0% / passed: 50% / failed: 0% / broken: 50%
/ 2 examples
1 specs
2 examples (1 passed, 1 broken)
32ms
Do you want me to create `Markdown::toHtml()` for you?
[Y/n]
Method Markdown::toHtml() has been created.
/ skipped: 0% / pending: 0% / passed: 100% / failed: 0% / broken: 0%
Markdown
15 - it converts plain text to paragraph
expected "<p>Hi, there</p>", but got null.
/ skipped: 0% / pending: 0% / passed: 50% / failed: 50% / broken: 0%
/ 2 examples
1 specs
2 examples (1 passed, 1 failed)
38ms
toHtml()メソッドがないので作りますか?
C:¥Users¥ishida¥src¥phpspec>vendor¥bin¥phpspec run --fake
/ skipped: 0% / pending: 0% / passed: 100% / failed: 0% / broken: 0%
Markdown
15 - it converts plain text to paragraph
expected "<p>Hi, there</p>", but got null.
/ skipped: 0% / pending: 0% / passed: 50% / failed: 50% / broken: 0%
/ 2 examples
1 specs
2 examples (1 passed, 1 failed)
67ms
Do you want me to make `Markdown::toHtml()` always return '<p>Hi,
there</p>' for you?
[Y/n]
Method Markdown::toHtml() has been modified.
/ skipped: 0% / pending: 0% / passed: 100% / failed: 0% / broken: 0%
/ 2 examples
1 specs
2 examples (2 passed)
27ms
toHtml()メソッドが常に"<p>Hi, there</p>"を返す
ようにしますか?
<?php
class Markdown
{
public function toHtml($argument1)
{
return '<p>Hi, there</p>';
}
}
src/Markdown.php
仮実装ができました。
Point
MarkdownクラスのSpecはMarkdownSpecクラスに書く
各exampleのメソッド名は、'it_'または'its_'
expectationは$thisに対して書く
つまりMarkdownSpecの中で$thisはMarkdownクラスのインスタン
スをラップしたオブジェクトとなる
このため、1つのSpecには1つのクラスのテストしか書けない
phpspec desc クラス名で、Specのひな形を作る
phpspec run --fakeで、仮実装を作る
スタブ
ファイル等から読み出したMarkdownをHTMLに変換するメソッド
Markdown::toHtmlFomReader(Reader $reader)
$reader->getMarkdown()を呼び出し、取得したMarkdownをHtmlに
変換する
指定した値を返却するダミーのReaderオブジェクトを作成する
(スタブ)
class MarkdownSpec extends ObjectBehavior
{
...
function it_convers_text_from_an_external_source()
{
// $reader->getMarkdown()が"Hi, there"を返すとする
$this->toHtmlFromReader($reader)
->shouldReturn("<p>Hi, there</p>");
}
spec/MarkdownSpec.php
class MarkdownSpec extends ObjectBehavior
{
...
function it_convers_text_from_an_external_source()
{
$reader->getMarkdown()->willReturn("Hi, there");
$this->toHtmlFromReader($reader)
->shouldReturn("<p>Hi, there</p>");
}
spec/MarkdownSpec.php
use Reader;
class MarkdownSpec extends ObjectBehavior
{
...
function it_convers_text_from_an_external_source(Reader
$reader)
{
$reader->getMarkdown()->willReturn("Hi, there");
$this->toHtmlFromReader($reader)
->shouldReturn("<p>Hi, there</p>");
}
spec/MarkdownSpec.php
exampleに仮引数を書くとPhpSpecが$readerを渡
してくれる
C:¥Users¥ishida¥src¥phpspec>vendor¥bin¥phpspec run --fake
...
Would you like me to generate an interface `Reader` for you?
[Y/n]
...
Would you like me to generate a method signature
`Reader::getMarkdown()` for you?
[Y/n]
...
Do you want me to create `Markdown::toHtmlFromReader()` for you?
[Y/n]
...
Do you want me to make `Markdown::toHtmlFromReader()` always
return '<p>Hi, there</p>' for you?
[Y/n]
Method Markdown::toHtmlFromReader() has been modified.
/ skipped: 0% / pending: 0% / passed: 100% / failed: 0% / broken: 0%
/ 3 examples
1 specs
3 examples (3 passed)
43ms
Reader::getMarkdown()と
Makkdown::toHtmlFromReader()の仮実装の
自動生成
モック
変換したHTMLをファイル等に出力するメソッド
Makdown::outputHtml($text, Writer $writer);
生成したHTMLをWriter::writeText($text)メソッドに出力する
指定したメソッドが呼ばれたかを検査可能なダミーのWriterオブ
ジェクトを作成する(モック)
use Writer;
class MarkdownSpec extends ObjectBehavior
{
...
function it_outputs_converted_text(Writer $writer)
{
// $writer->writeText("<p>Hi, there</p>")
// が呼び出されること
$this->outputHtml("Hi, there", $writer);
}
spec/MarkdownSpec.php
use Writer;
class MarkdownSpec extends ObjectBehavior
{
...
function it_outputs_converted_text(Writer $writer)
{
$writer->writeText("<p>Hi, there</p>")
->shouldBeCalled();
$this->outputHtml("Hi, there", $writer);
}
spec/MarkdownSpec.php
できました
class MarkdownTest extends ¥PHPUnit_Framework_TestCase
{
function test_output_converted_text()
{
$writer = $this->getMockBuilder('Writer')
->setMethods(['writeText'])
->getMock();
$writer->expects($this->once())
->method('writeText')
->with($this->equalTo("<p>Hi,
there</p>"));
$markdown = new Markdown();
$markdown->outputHtml("Hi, there", $writer);
}
但しPHPUnit4.5以降では、Prophecyという
phpspecのMockフレームワークを使うこともで
きます
ちなみにPHPUnitで書くと
コンストラクタ
Writerをメソッドの引数ではなくコンストラクタの引数として渡
し
$markdown = new Markdown();
$markdown->outputHtml($text, $writer); ではなく
$markdown = new Markdown($writer);
$markdown->outputHtml($text); にする
use Writer;
class MarkdownSpec extends ObjectBehavior
{
...
function it_outputs_converted_text(Writer $writer)
{
$writer->writeText("<p>Hi, there</p>")
->shouldBeCalled();
$this->outputHtml("Hi, there", $writer);
}
spec/MarkdownSpec.php
$writerをoutputHtmlの引数ではなく、
コンストラクタで渡したい
use Writer;
class MarkdownSpec extends ObjectBehavior
{
...
function let(Writer $writer)
{
$this->beConstructedWith($writer);
}
function it_outputs_converted_text($writer)
{
$writer->writeText("<p>Hi, there</p>")
->shouldBeCalled();
$this->outputHtml("Hi, there");
}
spec/MarkdownSpec.php
letは各exampleの前に実行される
letとexampleの引数には同じ$writerが渡される
(変数名が重要)
Point
スタブのメソッドが値を
返すこと
$reader->getMarkdown()
->willReturn("Hi, There")
モックのメソッドが呼び
出されること
$writer->writeText("<p>Hi, there</p>")
->shouldBeCalled()
コンストラクタに引数が
渡されること
$this->beConstructedWith($writer)
得られたもの
MarkdownクラスのSpec
Markdownクラスの実装
Readerインターフェース
Writerインターフェース
なぜinterface?
class FileStorage implements Reader, Writer {
...
}
class Markdown {
function toHtmlFromReader(Reader $reader) {...}
function toHtmlFromReader(FileStorage $reader) {...}
}
このメソッドに最
低限必要なものを
表せている
列車事故を防ぐ
((EditSaveCustomer) master.getModelisable()
.getDockablePanel()
.getCustomizer())
.getSaveItem().setEnabled(Boolean.FALSE.booleanValue());
master.allowSaveingOfCustomisations();
Specで設計を導き
出せばこのように
はなりづらい
The GOOS Book
に載っている例
サイクルを回し続ける
スペック→実装により隣接オブジェクトを設計し、さらに隣接オ
ブジェクトのスペック→実装を行う
が、隣接オブジェクトが既存のもの(ライブラリ、フレームワー
ク、Webサービス)の場合はどうする?
突然の
システム
境界!!
Hexagonal-Architecture
自分書かない部分のアダプタを
作り、その先は結合テスト等粒
度の大きいテストを行う
この時phpspecは使わない
(PHPUnit、Behat、Codeception
などを使う)
今日話さなかったこと
今日はUnit Testの話だけしましたが、本来はAcceptance Testあり
きです
単体テストをすれば必ず良い設計になるわけではありません。
しかし、単体テストは良い設計にするための手助けをしてくれま
す
phpspecはどんなテストにも有効なわけではありません。例えば
学習テストのようなケースではPHPUnitなどを使った方が良いで
しょう
まとめ
London school TDDでは、モックを使って、テスト対象と隣接する
オブジェクトとのコミュニケーションをテストする
外から中へアプローチすることで、必要なインターフェースを
導き出す
phpspecを使うとモックを簡単に作成することができる
モック出来ないものに対してはアダプタを作成する
phpspecは、London school TDDの考え方を上手く表現したツール
phpspecで書かれたThe GOOS Bookみたいな本が出るとうれしい
参考資料
モックによるインターフェースの発見
http://d.hatena.ne.jp/digitalsoul/20110927/1317079751
テスト駆動開発の進化
http://d.hatena.ne.jp/digitalsoul/20120920/1348104079
モックとスタブの違い
http://d.hatena.ne.jp/devbankh/201002
実践テスト駆動開発(GOOS)読んだ
http://qiita.com/kenjihiranabe/items/b951b6d98672167347fd
http://iakio.hatenablog.com/archive/category/phpspec
http://qiita.com/tags/phpspec
参考資料
phpspec2: SUS and collaborators(2012)
(http://everzet.com/post/33178339051/sus-collaborators)
phpspec2のalphaリリース時の作者によるコンセプトの解説
Konstantin Kudryashov - Design How Your Objects Talk Through Mocking
at Laracon EU 2014
(https://www.youtube.com/watch?v=X6y-OyMPqfw)
Laracon EUでの作者によるモックを使った開発手法に関する講演。
phpspec自体は使われていない
Does TDD really lead to good design?
(http://codurance.com/2015/05/12/does-tdd-lead-to-good-design/)
Detroit schoolとLondon Schoolの比較など
Laracast
(https://laracasts.com/index/phpspec)
LaravelやPHPに関するスクリーンキャスト。一部無料

More Related Content

What's hot

Modern PHP Programming @ PFI Seminar
Modern PHP Programming @ PFI SeminarModern PHP Programming @ PFI Seminar
Modern PHP Programming @ PFI Seminar
Sotaro Karasawa
 
TypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービューTypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービュー
Akira Inoue
 
Perl Hobby Programming - Games::BeLike::EightBIT ターミナルで8ビット風ゲームをつくろう
Perl Hobby Programming - Games::BeLike::EightBIT ターミナルで8ビット風ゲームをつくろうPerl Hobby Programming - Games::BeLike::EightBIT ターミナルで8ビット風ゲームをつくろう
Perl Hobby Programming - Games::BeLike::EightBIT ターミナルで8ビット風ゲームをつくろう
keroyonn
 

What's hot (20)

PSR-1 と PSR-2 を 5分でざっくり理解する
PSR-1 と PSR-2 を5分でざっくり理解するPSR-1 と PSR-2 を5分でざっくり理解する
PSR-1 と PSR-2 を 5分でざっくり理解する
 
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
 
Windows で拡張モジュールをビルドしてみた
Windows で拡張モジュールをビルドしてみたWindows で拡張モジュールをビルドしてみた
Windows で拡張モジュールをビルドしてみた
 
Modern PHP Programming @ PFI Seminar
Modern PHP Programming @ PFI SeminarModern PHP Programming @ PFI Seminar
Modern PHP Programming @ PFI Seminar
 
CodeIgniter入門
CodeIgniter入門CodeIgniter入門
CodeIgniter入門
 
JavaScript入門-基礎編
JavaScript入門-基礎編JavaScript入門-基礎編
JavaScript入門-基礎編
 
PHPの関数実行とその計測
PHPの関数実行とその計測PHPの関数実行とその計測
PHPの関数実行とその計測
 
WCO2012「PHP教室」
WCO2012「PHP教室」WCO2012「PHP教室」
WCO2012「PHP教室」
 
PECL operator で演算子オーバーロード
PECL operator で演算子オーバーロードPECL operator で演算子オーバーロード
PECL operator で演算子オーバーロード
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Ruby
 
PHP 8 と V8 (JavaScript) で速さを見比べてみよう!
PHP 8 と V8 (JavaScript) で速さを見比べてみよう!PHP 8 と V8 (JavaScript) で速さを見比べてみよう!
PHP 8 と V8 (JavaScript) で速さを見比べてみよう!
 
実"戦"CakePHP Plugin
実"戦"CakePHP Plugin実"戦"CakePHP Plugin
実"戦"CakePHP Plugin
 
PHPBLT#6 PHPの未来に入るかもしれない機能の紹介
PHPBLT#6 PHPの未来に入るかもしれない機能の紹介PHPBLT#6 PHPの未来に入るかもしれない機能の紹介
PHPBLT#6 PHPの未来に入るかもしれない機能の紹介
 
15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )
 
JIT のコードを読んでみた
JIT のコードを読んでみたJIT のコードを読んでみた
JIT のコードを読んでみた
 
TypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービューTypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービュー
 
JavaScriptの落とし穴
JavaScriptの落とし穴JavaScriptの落とし穴
JavaScriptの落とし穴
 
Perl Hobby Programming - Games::BeLike::EightBIT ターミナルで8ビット風ゲームをつくろう
Perl Hobby Programming - Games::BeLike::EightBIT ターミナルで8ビット風ゲームをつくろうPerl Hobby Programming - Games::BeLike::EightBIT ターミナルで8ビット風ゲームをつくろう
Perl Hobby Programming - Games::BeLike::EightBIT ターミナルで8ビット風ゲームをつくろう
 
Perl WAF Overview, with mod_perl - Hokkaido.pm#7 #hokkaidopm
Perl WAF Overview, with mod_perl - Hokkaido.pm#7 #hokkaidopmPerl WAF Overview, with mod_perl - Hokkaido.pm#7 #hokkaidopm
Perl WAF Overview, with mod_perl - Hokkaido.pm#7 #hokkaidopm
 
phpext-2-takagi
phpext-2-takagiphpext-2-takagi
phpext-2-takagi
 

Viewers also liked

CMSでWEBページを 更新するってどんな感じ? ~NetCommonsのやさしい更新画面、WYSIWYGを解説してみる~
CMSでWEBページを更新するってどんな感じ? ~NetCommonsのやさしい更新画面、WYSIWYGを解説してみる~CMSでWEBページを更新するってどんな感じ? ~NetCommonsのやさしい更新画面、WYSIWYGを解説してみる~
CMSでWEBページを 更新するってどんな感じ? ~NetCommonsのやさしい更新画面、WYSIWYGを解説してみる~
Masaki Goto
 
PostgreSQLの範囲型と排他制約
PostgreSQLの範囲型と排他制約PostgreSQLの範囲型と排他制約
PostgreSQLの範囲型と排他制約
Akio Ishida
 

Viewers also liked (20)

20150613 html5プロフェッショナル認定試験 レベル1技術解説セミナー
20150613 html5プロフェッショナル認定試験 レベル1技術解説セミナー 20150613 html5プロフェッショナル認定試験 レベル1技術解説セミナー
20150613 html5プロフェッショナル認定試験 レベル1技術解説セミナー
 
Introduction softlayer and bluemix
Introduction softlayer and bluemixIntroduction softlayer and bluemix
Introduction softlayer and bluemix
 
CMSでWEBページを 更新するってどんな感じ? ~NetCommonsのやさしい更新画面、WYSIWYGを解説してみる~
CMSでWEBページを更新するってどんな感じ? ~NetCommonsのやさしい更新画面、WYSIWYGを解説してみる~CMSでWEBページを更新するってどんな感じ? ~NetCommonsのやさしい更新画面、WYSIWYGを解説してみる~
CMSでWEBページを 更新するってどんな感じ? ~NetCommonsのやさしい更新画面、WYSIWYGを解説してみる~
 
OSC北海道 2015 ウェブサイト構築基盤、コーポレートサイトにちょうどいいCMS、baserCMSの紹介
OSC北海道 2015 ウェブサイト構築基盤、コーポレートサイトにちょうどいいCMS、baserCMSの紹介OSC北海道 2015 ウェブサイト構築基盤、コーポレートサイトにちょうどいいCMS、baserCMSの紹介
OSC北海道 2015 ウェブサイト構築基盤、コーポレートサイトにちょうどいいCMS、baserCMSの紹介
 
CircleCIを勝手に紹介・宣伝 + おまけ [OSC Hokkaido 2015 LT]
CircleCIを勝手に紹介・宣伝 + おまけ [OSC Hokkaido 2015 LT] CircleCIを勝手に紹介・宣伝 + おまけ [OSC Hokkaido 2015 LT]
CircleCIを勝手に紹介・宣伝 + おまけ [OSC Hokkaido 2015 LT]
 
センパイ!このプログラムクラッシュするんですけど。。。
センパイ!このプログラムクラッシュするんですけど。。。センパイ!このプログラムクラッシュするんですけど。。。
センパイ!このプログラムクラッシュするんですけど。。。
 
PostgreSQLの範囲型と排他制約
PostgreSQLの範囲型と排他制約PostgreSQLの範囲型と排他制約
PostgreSQLの範囲型と排他制約
 
PostgreSQLで学ぶBoyer-Moore-Horspoolアルゴリズム
PostgreSQLで学ぶBoyer-Moore-HorspoolアルゴリズムPostgreSQLで学ぶBoyer-Moore-Horspoolアルゴリズム
PostgreSQLで学ぶBoyer-Moore-Horspoolアルゴリズム
 
8-9-10=Jessie,Stretch,Buster
8-9-10=Jessie,Stretch,Buster8-9-10=Jessie,Stretch,Buster
8-9-10=Jessie,Stretch,Buster
 
よりよいPHPUnitの実行方法を求めて
よりよいPHPUnitの実行方法を求めてよりよいPHPUnitの実行方法を求めて
よりよいPHPUnitの実行方法を求めて
 
Osc2015北海道 札幌my sql勉強会_波多野_r3
Osc2015北海道 札幌my sql勉強会_波多野_r3Osc2015北海道 札幌my sql勉強会_波多野_r3
Osc2015北海道 札幌my sql勉強会_波多野_r3
 
日本のアニメ産業を爆速させるアニメAPIの開発と活用事例 (ニコニコ超会議2016 大和証券ステージ)
日本のアニメ産業を爆速させるアニメAPIの開発と活用事例 (ニコニコ超会議2016 大和証券ステージ)日本のアニメ産業を爆速させるアニメAPIの開発と活用事例 (ニコニコ超会議2016 大和証券ステージ)
日本のアニメ産業を爆速させるアニメAPIの開発と活用事例 (ニコニコ超会議2016 大和証券ステージ)
 
ラブライブ✕沼津 アニメタイアップについて
ラブライブ✕沼津 アニメタイアップについて ラブライブ✕沼津 アニメタイアップについて
ラブライブ✕沼津 アニメタイアップについて
 
クロスサイトリクエストフォージェリ(CSRF)とその対策
クロスサイトリクエストフォージェリ(CSRF)とその対策クロスサイトリクエストフォージェリ(CSRF)とその対策
クロスサイトリクエストフォージェリ(CSRF)とその対策
 
念願の北海道にUターンで帰ってきた - OSC北海道2015
念願の北海道にUターンで帰ってきた - OSC北海道2015念願の北海道にUターンで帰ってきた - OSC北海道2015
念願の北海道にUターンで帰ってきた - OSC北海道2015
 
好きな場所で働くということ。[Uターン転職編]
好きな場所で働くということ。[Uターン転職編]好きな場所で働くということ。[Uターン転職編]
好きな場所で働くということ。[Uターン転職編]
 
好きな場所で働くということ Iターン編
好きな場所で働くということ Iターン編好きな場所で働くということ Iターン編
好きな場所で働くということ Iターン編
 
Osc2015 hokkaido postgresql-semi-stuructured-datatype
Osc2015 hokkaido postgresql-semi-stuructured-datatypeOsc2015 hokkaido postgresql-semi-stuructured-datatype
Osc2015 hokkaido postgresql-semi-stuructured-datatype
 
秋葉原IT戦略研究所のご紹介(2016/05/04)
秋葉原IT戦略研究所のご紹介(2016/05/04)秋葉原IT戦略研究所のご紹介(2016/05/04)
秋葉原IT戦略研究所のご紹介(2016/05/04)
 
はじめよう TypeScript - 入門から実践まで - 素の JavaScript とはさようなら!
はじめよう TypeScript - 入門から実践まで - 素の JavaScript とはさようなら!はじめよう TypeScript - 入門から実践まで - 素の JavaScript とはさようなら!
はじめよう TypeScript - 入門から実践まで - 素の JavaScript とはさようなら!
 

Similar to phpspecで学ぶLondon School TDD

20110820 metaprogramming
20110820 metaprogramming20110820 metaprogramming
20110820 metaprogramming
Masanori Kado
 
Php in ruby
Php in rubyPhp in ruby
Php in ruby
do_aki
 
Web デザイナーが身に付けておきたい定番スキル ーPHP 初級編ー
Web デザイナーが身に付けておきたい定番スキル ーPHP 初級編ーWeb デザイナーが身に付けておきたい定番スキル ーPHP 初級編ー
Web デザイナーが身に付けておきたい定番スキル ーPHP 初級編ー
Kite Koga
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniter
Masanori Oobayashi
 

Similar to phpspecで学ぶLondon School TDD (20)

Phpcon tokyo 20120_bigginer
Phpcon tokyo 20120_bigginerPhpcon tokyo 20120_bigginer
Phpcon tokyo 20120_bigginer
 
php in ruby
php in rubyphp in ruby
php in ruby
 
20110820 metaprogramming
20110820 metaprogramming20110820 metaprogramming
20110820 metaprogramming
 
FukuokaPHP 3
FukuokaPHP 3FukuokaPHP 3
FukuokaPHP 3
 
Php in ruby
Php in rubyPhp in ruby
Php in ruby
 
第21回Creators MeetUp
第21回Creators MeetUp第21回Creators MeetUp
第21回Creators MeetUp
 
React.jsでクライアントサイドなWebアプリ入門
React.jsでクライアントサイドなWebアプリ入門React.jsでクライアントサイドなWebアプリ入門
React.jsでクライアントサイドなWebアプリ入門
 
PHP初心者セッション2023 〜ChatGPT時代の簡単な始め方〜
PHP初心者セッション2023 〜ChatGPT時代の簡単な始め方〜PHP初心者セッション2023 〜ChatGPT時代の簡単な始め方〜
PHP初心者セッション2023 〜ChatGPT時代の簡単な始め方〜
 
FuelPHPをさわってみて
FuelPHPをさわってみてFuelPHPをさわってみて
FuelPHPをさわってみて
 
Ruby on Rails Tutorial
Ruby on Rails TutorialRuby on Rails Tutorial
Ruby on Rails Tutorial
 
PHPCON_TOKYO_2022_Bigginer.pptx
PHPCON_TOKYO_2022_Bigginer.pptxPHPCON_TOKYO_2022_Bigginer.pptx
PHPCON_TOKYO_2022_Bigginer.pptx
 
MoteMote Compiler Plugin
MoteMote Compiler PluginMoteMote Compiler Plugin
MoteMote Compiler Plugin
 
Web デザイナーが身に付けておきたい定番スキル ーPHP 初級編ー
Web デザイナーが身に付けておきたい定番スキル ーPHP 初級編ーWeb デザイナーが身に付けておきたい定番スキル ーPHP 初級編ー
Web デザイナーが身に付けておきたい定番スキル ーPHP 初級編ー
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniter
 
PHPの今とこれから2019
PHPの今とこれから2019PHPの今とこれから2019
PHPの今とこれから2019
 
PHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 とPHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 と
 
【10人限定】1日でマスター!word pressのための「php:mysql講座」
【10人限定】1日でマスター!word pressのための「php:mysql講座」【10人限定】1日でマスター!word pressのための「php:mysql講座」
【10人限定】1日でマスター!word pressのための「php:mysql講座」
 
Apacheの展望とmod_perlの超絶技巧 #yapcasia
Apacheの展望とmod_perlの超絶技巧 #yapcasiaApacheの展望とmod_perlの超絶技巧 #yapcasia
Apacheの展望とmod_perlの超絶技巧 #yapcasia
 
CakePHP 1 to 2 Migration tips 100
CakePHP 1 to 2 Migration tips 100CakePHP 1 to 2 Migration tips 100
CakePHP 1 to 2 Migration tips 100
 
Web技術勉強会23回目
Web技術勉強会23回目Web技術勉強会23回目
Web技術勉強会23回目
 

More from Akio Ishida (8)

Getting start with knockout.js
Getting start with knockout.jsGetting start with knockout.js
Getting start with knockout.js
 
XIDを周回させてみよう
XIDを周回させてみようXIDを周回させてみよう
XIDを周回させてみよう
 
Local php-100828 2
Local php-100828 2Local php-100828 2
Local php-100828 2
 
Rubysapporo Stringsearch
Rubysapporo StringsearchRubysapporo Stringsearch
Rubysapporo Stringsearch
 
Ruby Postgres 2009
Ruby Postgres 2009Ruby Postgres 2009
Ruby Postgres 2009
 
使いこなそうGUC
使いこなそうGUC使いこなそうGUC
使いこなそうGUC
 
textsearch_jaで全文検索
textsearch_jaで全文検索textsearch_jaで全文検索
textsearch_jaで全文検索
 
Ruby Postgres
Ruby PostgresRuby Postgres
Ruby Postgres
 

Recently uploaded

Recently uploaded (12)

論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 

phpspecで学ぶLondon School TDD