phpのメタプログラミングでテストを自作してみた。

<?php
/*
 * テストの基底クラス
 * 
 * - __run__(), assert()以外の関数はすべてテストされる。
 * - assert()関数でエラーチェックを行うことができます。
 */
abstract class TestBase {
  /*
   * テスト実行
   * 例外を吸収します
   */
  public function __run__() {
    $class_name = get_called_class();
    $method_names = get_class_methods($class_name);
    // $method_names = get_class_methods(__CLASS__);

    echo $class_name . PHP_EOL;
    foreach ($method_names as $method_name) {
      if ($method_name === __FUNCTION__) {  continue; }
      if ($method_name === "assert") {  continue; }

      try {
        $this->$method_name();

        echo "  o " . $method_name . PHP_EOL;
      } catch(Exception $e) {
        echo "  x " . $method_name . ": " . $e->getMessage() . PHP_EOL;
      }
    }
  }

  /*
   * エラーチェック
   * @param boolean $flag trueの場合エラーが発生する
   * @param string $message エラーメッセージ
   * @throws Exception 
   */
  protected static function assert($flag, $message = "") {
    if ($flag) { 
      // $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
      // throw new Exception($trace[0]["line"] . ": " . $message);

      $trace = debug_backtrace();
      throw new Exception($trace[0]["line"] . ": " . $message);
    }
  }
}

/*
 * 汎用的な関数のテストを行います。
 */
class GenericTest extends TestBase {

  function array_marge() {
    $v = [
      "test1" => "100",
      "user" => "root",
      "password" => "root",
    ];
      
    $params = [
      "dsn" => "localhost",
      "ip" => "192.168.1.1",
      "user" => "user",
      "password" => "user",
    ];

    $v = array_merge($v, $params);

    $data = [
      array_key_exists("test1", $v),
      array_key_exists("user", $v),
      array_key_exists("password", $v),
      array_key_exists("dsn", $v),
      array_key_exists("ip", $v),
    ];

    foreach ($data as $d) {
      self::assert(!$d, "error.");
    }
  }

   function intentional_test() {
      self::assert(true);
  }

  function file_test() {
    $path = '/core/Request.php';

    self::assert(!file_exists($path), "file does not exist.");
  }

  function url_split() {
    $url = parse_url('http://example.com/project/controller/action/param1/param2');
    self::assert($url["scheme"] !== "http", $url["scheme"]);
    self::assert($url["path"] !== "/project/controller/action/param1/param2", $url["path"]);

    $sections = explode('/', $url["path"]);
    self::assert($sections[0] !== "");
    self::assert($sections[1] !== "project");
    self::assert($sections[2] !== "controller");
    self::assert($sections[3] !== "action");
    self::assert($sections[4] !== "param1");
    self::assert($sections[5] !== "param2");
  }

}

$gt = new GenericTest();
$gt->__run__();

出力

$ php test.php

GenericTest
  o array_marge
  x intentional_test: 88:
  x file_test: 94: file does not exist.
  o url_split