PHPUnitでdataProviderが動作せずに時間を食った話

概要

PHPUnitを使って、PHPのテストコードを書いていたところ、dataProviderが動かなくて、数時間悩みました。
備忘録として、情報を残しておきます。

なにがあった?

下記のようなテストコードを書いて、PHPUnitを実行したところ、 rgumentCountError: Too few arguments to function ExampleTest::checkExceptionTest()
というように引数があってないよーというエラーが発生しました。

dataProvider のDoccommentはTypoもなく、メソッド名も適切な名前になっていました。

class ExampleTest extends TestCase
{
    /**
     * @var Example
     */
    public $_obi;

    public function __construct()
    {
        parent::__construct();
        $this->_obj = new Example();
    }

    public function checkExceptionDataProvider():array
    {
        return [
            'number 1' => [1, \LogicException::class, 'number 1'],
            'number 2' => [2, \ErrorException::class, 'number 2'],
        ];
    }

    /**
     * @test
     * @dataProvider checkExceptionDataProvider
     */
    public function checkExceptionTest($param, $errorClass, $errorMessage)
    {
        $this->expectException($errorClass);
        $this->expectExceptionMessage($errorMessage);

        $this->_obj->checkExecption($param);
    }
}

なにが原因だった?

既存でdataProviderを使っている箇所と見比べると、テストケースの初期化として__constructを使っていることが、差分として発生していました。
そのため、__constructsetUpに置き換えて見ると、正常にテストは動きました。

PHPUnit マニュアル – 第4章 フィクスチャを見ると、テストデータを生成する際はsetUpを使えと書いてあるので、そもそも__constructを使うのが亜流ということですね…。

PHPUnitのコードを読めば、エラーの原因が詳細にわかりそうなのですが、余力がないの今日はここまで。

CakePHP2系でComponentの単体テストを行って躓いた話

概要

CakePHP2系のアプリケーションに、新規でComponentを作成した。 そのComponentに対して、単体テストを行うとしたところ躓いたので残しておく。

内容

Componentに対して単体テストを作成し、公式ドキュメントを参考にsetUpに下記を記述。

public function setUp()
{
    parent::setUp();
    $CakeRequest      = new CakeRequest();
    $CakeResponse     = new CakeResponse();
    $this->Controller = new テスト用Controller($CakeRequest, $CakeResponse);
    $Collection       = new ComponentCollection();
    $this->Component = new テスト対象のComponent($Collection);
    $this->Component->startup($this->Controller);
}

これでテストケースを書いて実行したところ、テストケースが正常に走らなかった。 エラーログを確認したところ、下記が出力されている。

Error: Fatal Error (1): Call to a member function メソッド名() on a non-object

この出力されたメソッドはテスト用Controllerの親クラス(AppController)に定義されており、Webページとしてアクセスする分には問題なく利用できている。

何が原因なんだ…。

解決

テストケースのsetUp内に $Collection->setController($this->Controller); を追加することで解決した。

エラーログを見ると、メソッドがないと怒られているので テスト対象のComponent 内でControllerから受け取った値を見てみた(下記コードのgetController結果)。 すると、値がnullとなっており、Controllerがセットされていないことがわかった。

public function __construct(ComponentCollection $collection, $settings = array())
{
    $this->Controller = $collection->getController();
    parent::__construct($collection, $settings);
}

getがあるなら、setがあるだろうとCakePHPのコードを確認したところ、setControllerがあったのでビンゴ。 setControllerを呼び出すことで解決した。

public function setUp()
{
    parent::setUp();
    $CakeRequest      = new CakeRequest();
    $CakeResponse     = new CakeResponse();
    $this->Controller = new テスト用Controller($CakeRequest, $CakeResponse);
    $Collection       = new ComponentCollection();
    $Collection->setController($this->Controller);
    $this->Component = new テスト対象のComponent($Collection);
    $this->Component->startup($this->Controller);
}

以上、誰かのためになったら良いなと思い残しておきます。 最後まで読んで頂きありがとうございました。

参考

https://book.cakephp.org/2.0/ja/development/testing.html#id27

PHPerKaigi2018の感想

概要

PHPerKaigi2018に参加してきました。
初めて参加したカンファレンスですが、率直に言って最高だったので感想を記載していきます。

行く前の自分

  • カンファレンス行ったことなくて怖い
  • しょぼい質問したらマサカリが飛んで来るんじゃないか
  • 知り合い居ないから懇親会でぼっちになるかも

こんな気持を抱えていましたが、同時に外部から知識を得たいという思いもあったので、腹をくくって参加してきました。

  • PHP5→7へのバージョンアップに悩んでいる
  • レガシーなコードやテーブルへの扱いに悩んでいる
  • フレームワークのアップデートへの追従はしんどい
  • Apacheとnginxはどっちが主流なのかな

現在自分が携わっている環境を改善するため、
そして、決めてとなったのは主催者長谷川さんからのこの一言で参加を決意しました。

行った後の自分

最高に楽しかった!

  • カンファレンス行ったことなくて怖い
    • 全然優しかった
  • しょぼい質問したらマサカリが飛んで来るんじゃないか
    • 全くそんなことなかった。むしろ「本を読め!」って言われないで、解説してくれた
  • 知り合い居ないから懇親会でぼっちになるかも
    • 1人でいたら話しかけてくれた

行く前に思っていたことの殆どは杞憂となりました。
それどころから、前夜祭で始まる前からビールを飲めて、カンファレンスを楽しい気持ちで迎えられました。
(最初はカンファレンスはビール飲みながらやるものかと思ったw)

個々の感想

前夜祭

PHPでテスティングフレームワークを実装する前に知っておきたい勘所 #phperkaigi

Unitテスト=PHPUnitと簡単に考えていたが、別にPHPUnitを使わなくてもいいなと言われて気付きました。
PHPUnitでもPower-assertが使えたら便利だなと思いました。

うずらさんの飛び入りLT in PHP7.1 is fast(?)

すごいハイテンションで進む上に、ものすごいtechなのでついていくのに大変でした。
しかし、ふざけた口調でとてもtechなことを行っていてすごいなと思いました。

PHP と SAPI と ZendEngine3 と

PHPの内部が全然知らなかったので、ついていけない部分がありました。
PHPのライフサイクルやメモリ消費が減った理由について話があったので、後でスライド読み返し、咀嚼します。

大統一PHP

ビールが進んでいました笑 ReactPHPは以前から興味を持っていたので、発表は興味深いものでしたが、如何せん自分にはレベルが高い話でした…。
Swooleも面白そうに感じたので、ReactPHPと合わせてどこかで学習しておきたい。

全体

入っていきなりビールを渡されて、「カンファレンスはお酒を飲みながらやるのか!」と驚きました笑。
お酒のおかげで初参加の緊張が解せたのか、リラックスした気持ちでセッションの内容を聴くことができました。

当日

PHPerのためのWebサービスのモニタリングの話

普段から「サーバに導入しているzabbixを使えていないなー」と思っていたので、勉強になる内容と耳の痛い内容でした笑。
一先ず、会社に戻ったらモニタリング会をやってみようと思いました。

SOLIDの原則ってどんなふうに使うの?

実はSOLIDの原則を知らなかったので、タイトルを見てあまり興味がわかないと思っていました。
しかし、セッションを聞いていると自分がうまくできていないコードの設計の話で、とても勉強になりました。
理解できていなかった部分もあったので、スライドは後で見返すとともに、自分でもTODOアプリを作って、後藤さんのものと比べてみようと思いました。
(こんな先輩が欲しかったな…)

CakePHP相談会

チーム内でCakePHP3系への移行が行われているので参加。
参加していたメンバーも、フレームワークへの追従について悩んでいたので、結構参考になりました。

Hackで作るマイクロフレームワーク

今回のイベントの大本命です。
以前からHHVM/Hackに興味を持っていたので、ノリノリで参加しました。
言語にかぎらず、設計の部分でついていけないところがあったので、後で内容を見返して、HHVM/Hackで漢になろうと思います。

RDBMS相談会

アンカンファレンスで発生したRDBMS相談会。
既存のイケてないテーブルをどうするか、という点で悩んでいたので、

そーだい@初代ALF (@soudai1025) | Twitterさんに相談できてよかった。

PHPStanで始める継続的静的解析 #phperkaigi /php-static-analysis

実はPHP7を使っていないので、型指定の恩恵がイマイチピンときていなかったのです。
この発表でメリットがわかって良かったです。

LT

HackのAsyncCurlで死んだ話

これは自分で挑んだときに参考になりそうです。

忘れた頃にMcryptは廃止される

レビューをもらいやすい細かい プルリクの切り分け方 at PHPerKaigi 2018

Lumenで堅牢なAPIを設計する。

速習・Dockerと学ぶPHP / 20180310-PHPerKaigi

スタートアップしてからの失敗の数々

ISUCONを社内向け1人参加型ISUCONにアレンジしてみた

どれも楽しく為になる内容でした。

最後に

つらつらと感想を書きましたが、本質的に伝えたい事は、
初めて参加したカンファレンスがPHPerKaigi2018で良かった です!
主催者もスタッフもスピーカーも参加者も、みんなが盛り上げようとして祭りのようでした。

自分もカンファレンスにスピーカーやスタッフとして参加してみたい!
もっとカンファレンスに参加したい!
と思えるPHPerKaigi2018でした。

主催者もスタッフもスピーカーも参加者も、皆さんありがとうございました!

PHPerKaigi2018雑メモ

最初に

これは自分が書いたメモをただ挙げただけの内容になる。
感想とかは次の記事で。

前夜祭

オープニングトーク

  • PHPerKaigiは双方向コミュニケーション
  • 長谷川さんがビール煽って楽しそう

PHPでテスティングフレームワークを実装する前に知っておきたい勘所 #phperkaigi

  • PHP標準のテスト機能がある
    • phptってやつ
  • ライブラリとフレームワークの違い
    • 呼び出しが逆
  • アプリケーション側でcookieとかheaderを呼ぶとテストで死ぬ
    • それぞれラッパーして上げないとテストできない
Q:Power-assertって実運用で使える?  
A:結構大変。eval使って悪いことしている。

うずらさんの飛び入り LTPHP7.1 is fast(?)

  • PHP7.1は早い
  • ベンチマークツールによって結果が大きく違う
    • keepaliveの扱いが違ったり、HTTP1.1に対応しているかどうかで差がある
Q:` php -S ` は試していないの?  
A:PHP公式でNGが出ているので試していない。

PHP と SAPI と ZendEngine3 と

QA

Q:USE_ZEND_ASSOCは0に出来るけどなんの用途で使う?  
A:なんとも言えない。デバッグなので使うのではないか
Q:OPCODECHACEは全てのコードでキャッシュされる?  
A:どこでもキャッシュされる。

大統一PHP

ビールが加速していく。

我々はhttpdになりたいパワーワード
(要約するとGoやRubyと違って、PHP自身はhttpdになってない)

  • ReactPHPで早くしようと思ったら設計がいるぞ
    • ぶっちゃけ簡単に使ったら遅いー
    • 実行したスクリプトが死んだらサーバも死ぬぞー
Q:なんで1バイナリにまとめた(モチベ)?  
A:他の言語に合わせる。Docker使っている人に合わせるため。
Q:ReactPHPを本番で使っている?  
A:APIで使っている。HTMLとか投げるとしんどい。  
  早いとかそういうモチベを持っていると思うが、そのモチベだとシングルトンにしないと行けなくて大変よ。  
  最近はPsr7に対応して良くなっている。

本編

PHPerのためのWebサービスのモニタリングの話

PHPアプリケーションの監視の話。

  • サーバサイドは自分たちの管轄なので、モニタリングしやすいし手が打ちやすい
  • クライアント(JS)は不可解な事が起きるのでモニタリング大事
  • DNSとかアンコントローラブルだけど、モニタリングはいるよ
  • サーバサイドはNew Relicがおすすめ
  • 監視は可視化するのが大事 →時系列でデータを持たないと今の状態が分からない
  • ダウンロード数や課金数もモニタリングすると良い →サイトはダウンしてないけど、ダウンロード数が急激に減ったら問題が起きたとわかる
  • アプリケーションエンジニアは2015年Webサーバアーキテクチャ序論 - ゆううきブログを良い
  • パフォーマンスモニタリング会とかを2週間に1回くらいやっておく良い →何か問題が起きたか気付ける
  • 計測→観測することで「感が働かせるようになる」 →未来を予測できるようになる
Q:DB監視について、自分の会社でAWSのAuroraを使っていて、DBが落ちる障害が起きたが、インスタンスサイズを最大にあげて終わりにした。  
よくなっているが、価格が高すぎて困っている。  
どうしたら適切なインスタンスサイズを選べるか?何を見ればよいの? 
A:アプローチは間違ってない。  
CPU・メモリ・ディスクIOが問題の9割を占める。  
チューニングしてどれかを下げられるか。  
CPU50%を下回れば良い。ディスクIOはディスクサイズに依存する。  
メモリはバッファプールに乗っているか、インデクスが効いているか。  
発行されたSQLがきちんと実行されているかを見る。  
SlowQueryLogなどを見る。

SOLIDの原則ってどんなふうに使うの?

  • TODOが2週類あるという状態なので3つ目が増えることも想定する必要がある
  • オープン=機能が拡張できる、クローズド=修正を行わない
    • 原則を適応する範囲はバリエーションを追加する場合
Q:TODOの表示をTODOのクラスがもてばいいのではないか
表示部分を別クラスに切り出したのはなぜ
A:TODOEntityの中に持たせれば確かに他のコードを書き直す必要はない。しかし軸が一つならうまくいく可能性が高いが、表示処理がPDF出力とか、があった場合に、Entityの中に、showPDFみたいなのが必要にってしまう。
考えすぎても先に進めないが、よく追加される要件は考慮に入れておいた方が良い。

CakePHP相談会

Join CakePHP on Slack!で色々話がある。
→最近は3.6ベータの話とか。

1→3へアップデートの話

  • 7.0でCakephp1.3を動かした会社がある
    • coreに手を入れたと思われる
      • 4系で動くことを想定しているので、普通には上がらない
    • パスワードの共有化とかセッションの共有化は作り込みが必要
  • 1と3を同じリポジトリに入れ、3でリクエスト受けて、3になかったら1に流す実装をしていた

2→3のアップデートシェルはある
→あんまり期待できないかもだけど…

CakePHP1.3はどこまでのPHPバージョンで行けるか

  • CakePHP1.3はPHP5.6までは行ける!!
    • coreに手を入れてなくてもいける
      • もっともアプリケーションが動いているだけなので、全部の機能が使えるというわけではない
      • デバッグオプション入れるとCakeのコードでいっぱいWarming吐く
  • mysql関数が怪しいかもしれぬ…、mysqliなら問題なし

アップデートの話

  • CakePHP2.10は4が出てから1年はバグフィックスされる
  • CakePHP4.0の構造はどうなる?
    • 3.6で非推奨なものを使わなければ行けるぞ
    • 4からは最新の機能をガシガシ使っていく流れになっている
    • 3.6と4で差がないならなぜバージョニングが違う?
    • おそらくPHP5の互換を切るかどうかでバージョニングしている
  • ランサーズでCakeのcookbookを読む会をやっている
    • ランサーズの人が読んで、参加メンバーで議論する
    • 1, 2, 3と上げるためにやっている
  • 2から3に上げるとき
    • 2のCustomFinderを作っておけば、3のCustomFinderに上げやすい
  • Cookbookにバージョンごとのアップグレードの話が載っている
  • バージョンアップで挙動が変わっていないことをどう担保する?
    • PHPUnitテストでカバーするのきつない?
    • レニウムとかでやると良いのかな
  • PHPフレームワークのバージョンを上げないでなんとかならないか?
    • PHPのバージョンにパッチを当て続けるよりは、PHPのバージョンを上げた方が良いのでは…
    • PHP7になって内部のメモリ構造は変わったり速度も上がったのでお得だし

Hackで作るマイクロフレームワーク

自分的には大本命。
「皆さんHack使っていると思うんですよね」パワーワード

  • .hhconfigでPHPのコードを動作させないように出来る
    • かなり男になれる
  • hhiを使うことでATOMVScodeならHackをかけるぞ
  • PsrはHackを想定していない
  • HHVM-Autoload
    • Composerのhack版。絶対使おうな
  • HackでPsr11のmixedの扱い
    • mixed変数をそのまま使うと型がわからないため、タイプチェッカーがエラー扱いをする
        * 配列であれば、配列だよってコードで明示する
    • mixedは使わない方が良いよ
  • Hack≠PHP
    • hackはPHPの配列にフィールドを設定できる
  • 返ってきたJSONに対して型をチェックできる
    • 出力できるJSONもチェックできる
  • 要点はPHPと同じで小さなライブラリの集合体になっていく
    • symfonyもサポートが切れ、残るはZendのみ
Q:Hack > PHP7の部分はどこ?  
A:IOの消費が良い、それくらい。
Q:初めて型の厳格な言語に触る場合、おすすめできる言語か?  
A:型に厳格な言語を初めて触る方にはおすすめしない。  
→今ならGo言語かPHP7の方がよい。
Q:HackでベターなWebフレームワークはある?  
A:ない。今なら先駆者になれるチャンス!

アンカンファレンス - MySQL相談会

Q:MySQLの技術的負債をどう解決する?
A:データベース・リファクリングに書いてある。
 テーブル構造変更だけじゃなく、アプリケーションと相互に修正を加えていく必要がある

PHPStanで始める継続的静的解析

  • dynamic=動かしてみる
    • モックを工夫しないと誤作動が起きる
  • static=動かさずに読む
  • PHPStanはautoloadを設定する]
    • Composerの関係で、厳密にはコードを実行している
      • composerが標準化したことで、autoloadを実行しても問題なし、という見解が出来るようになった
  • @return $this ←メソッドチェインしてますの合図(PHPdoc)

極論

  • 複雑な型はPHPでは表現できないので、困ったらmixedでPHPの原点に還ろう
    • そういう箇所はUnitテストを厚めに行こう

LT

HackのAsyncCurlで死んだ話

  • curl_multi_execが原因でこけていた。
  • 世に転がっている「HHVMが謎の死を遂げた」も上記が原因かもね。

レビューをもらいやすい細かい プルリクの切り分け方 at PHPerKaigi 2018

既存の振る舞いを変えないものはどんどん先出しでリリースしちゃえ。

Lumenで堅牢なAPIを設計する。

Lumenで出来るセキュリテー対策に関するTips - Fendo181 - Scrapbox
* Lumen使ってみたいなと思っていたので気になっていたLT。 * まとめの内容は良いオチがついていたw

ISUCONを社内向け1人参加型ISUCONにアレンジしてみた

はじめに

地方で活動しているPHPerです。

技術やキャリアについて考えるため、ブログを始めてみました。