ささきしき

チラシ

【化石】PHPUnitでtraitのprivateメソッドをテストする(3版;2018-11-06)

片方ずつの話ならググればすぐ出てくるんですけど両方一気にやってるのを見かけなかったので、まぁ組み合わせればいいだけなんですけど備忘録がてら書いておきます。

利用バージョンは以下。

  • PHPUnit 7.3.5
  • PHP 7.1.9
  • Composer/autoload で名前解決してます

setUP()で対応する場合

// MyTrait.php
trait MyTrait
{
  private function privateMethod($arg)
  {
    return true;
  }
}
// traitTest.php
use \PHPUnit\Framework\TestCase;
use MyTrait;

final class MyTreatTest extends TestCase
{
  public function setUp()
  {
    $this->mock  = $this->getMockForTrait(MyTrait::class);
    $this->class = new \ReflectionClass($this->mock);
  }

  public function testPrivateMethod()
  {
    $method = $this->class->getMethod("privateMethod");
    $method->setAccessible(true);

    $argument = "hogefuga"; // optional
    $this->assertTrue($method->invoke($this->mock, $argument));
  }
}

setUpBeforeClass()で対応する場合

trait側は同じなので省略。

// traitTest.php
use \PHPUnit\Framework\TestCase;
use MyTrait;

final class MyTreatTest extends TestCase
{
  protected static $mock;
  protected static $class;

  public static function setUpBeforeClass()
  {
     self::$mock = (new class extends TestCase {})->getMockForTrait(MyTrait::class);
     self::$class = new \ReflectionClass(self::$mock);
  }

  /**
   * @dataProvider dp_PrivateMethod
   */
  public function testPrivateMethod($argument)
  {
    $method = self::$class->getMethod("privateMethod");
    $method->setAccessible(true);

    $this->assertTrue($method->invoke(self::$mock, $argument));
  }

  public function dp_PrivateMethod()
  {
    $mock = $this->getMockForTrait(MyTrait::class);
    $class = new \ReflectionClass(self::$mock);
    $method = $class->getMethod("anotherPrivateMethod");
    $method->setAccessible(true);

    return [
      "argument #1" => $method->invoke($mock, 1),
      "argument #2" => $method->invoke($mock, 2)
    ];
  }
}

メモ

  • たぶんこれで動くと思うんですが、適当に抜き出したので万一動かなかったら大変申し訳ない。言われたら直します。
  • getMockForTrait()
  • ReflectionClass()
  • getMockForTrait()PHPUnitReflectionClass()PHPの標準機能
    • getMockForTrait()は文字通りTraitを受け取ってクラスっぽく展開するメソッド。ただしpublicスコープしか利用できない
    • ReflectionClass()はクラスを受け取ってリバースエンジニアリングできたりするクラス。クラスが持ってるプロパティ・メソッドの一覧を出したり、本件みたいにprivateメソッドを外部から叩いたりできる
  • テストしたいメソッドが1つだけならReflectionMethod()ってクラスのほうが楽そう。というかそっちを紹介する投稿のほうが多い。なんでだろうか
  • setUp()で初期化しないでsetUpBeforeClass()でやりたいものだが、staticメソッドゆえ$thisが生えないので断念
    • 無名クラスを生やしてその場で殴ればselfに代入できる。黒魔術感はある。好みっぽい
    • __construct()でやりたいものだが、なんか失敗した()ので断念
    • テスト件数増えてくるとこの辺所要時間に響くかもしれない。要検討

編集履歴

  • 6 Nov. 2018
    • dataProvider()の仕様についての話題を修正。
  • 23 Sep. 2018
    • setUpBeforeClass()でもできたので追記。
    • dataProvider()での挙動を追記。
  • 21 Sep. 2018
    • 初版

以上

オフ会(≒レセプション)開催に係る、QoR向上のススメ

Quality of Reception.

オフ会って言うと極端な話、ネットで知り合った人間2人がペアチケ当ててライブに出向くのも該当するけれど、そうではなく、「十数人~数十人の人間が、集団として何らかの目的を持って、有志によって開催されたイベントに参加する」くらいの規模のレセプション・パーティーについて語っていると思ってくだしあ。 いまいち想像がつかない方は、そうだなぁ、アニメやマンガで見るような「立食パーティー」ってイメージの、もっと小規模な寄合っぽい、なんかそういうものを想像してみてください。多分。

というわけで、そういうレセプションのスタッフ(ホスト)として参加したときに、何に注意したらより良いものになるのか(なりそうなのか)、という意見を、思いつく限りメモしておこうと思います。

箇条書き結論

  • 連絡方法は1つだけ用意する
  • 会場を下見して、イベント時の人の流れを大まかに把握する
  • 名簿は確実に用意する
  • 金銭の話をするときに「とりあえず」は厳禁
  • 現地機材の徹底確認(できる限り下見しろ)
  • 環境依存性の高いデータは用意しない
  • 私はお前じゃないし、お前は私じゃない
  • 必ずしも参加者全員が味方ではない
  • 必ずしも参加者全員は味方ではない
  • 参加を断る権利も、参加しない権利もある

おわりに・免責

いろいろ思いつくままに書き連ねましたが、あくまで私個人の意見感想であり、所属する企業・団体、ホスティングサーバーの運営企業とは関係なく、特定の政治的思想、宗教的価値観を奨励・批判するものでもありません。また一部明示した箇所を除き、特定の企業・団体や個人、イベント等について言及されたものではありません(お定まりの定型句)。 あくまで「私がホスト側でイベントを興すならこれくらいしたいし、できれば他人がホストになったときにもしていて欲しいけれど、まァ理想論ね。理想論。」という程度の話です。

この文章を大真面目に肯定的に捉えて実践しようとしなくていいし、この文章を大真面目に批判的に捉えて義憤に駆られなくていいです。

以下本旨

続きを読む

日記 30 Sep, 2018

なんとか今月も更新できた(突然の目標宣言)

7月から溜まってたカードゲームのやりこみ報告です。

f:id:sota_n:20180930230959p:plain

f:id:sota_n:20180930231016p:plain

f:id:sota_n:20180930231028p:plain

だんだん達成率が悪くなってるの良くないですね。10月期はがんばるぞい。

…っていうか今見返したら9月分だけトリミング位置間違えてますね。なんだそれ。