LoginSignup
7
3

More than 5 years have passed since last update.

正規表現のテストをする (モノリシックなクラスを作る篇)

Posted at

こう、適当に正規表現をリテラルに書いちゃったりすると、結構脆弱性の温床になっちゃうじゃないですか。

対策はいろいろ思いつきますが、今回はおてがるに実行なやつから書いていきます。

汎用的なパターンをまとめる

  • よいところ
    • 似たようなパターンをリテラルでコピペされなくなる
  • わるいところ
    • 意図しない使われかたをされたり、うっかりパターンに手を入れて処理をぶっこわすことがありうる

クラスにまとめてみる

RegExpPattern.php
<?php

/**
 * 汎用的な正規表現をこのクラスに記述する
 */
final class RegExpPattern
{
    const DATETIME = '/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/';
    const DATE = '/\d{4}-\d{2}-\d{2}/';
}

PHPUnitでテストしてみる

<?php

final class RegExpPatternTest extends TestCase
{
    /**
     * {@see RegExpPattern} に定義された定数が、最低限不正な表現ではないことを保障
     *
     * @dataProvider validRegExpProvider
     */
    public function testValidRegEx($name, $pattern)
    {
        $actual = preg_match($pattern, '');
        $this->assertNotFalse($actual, '不正な正規表現です');
        // 空文字列とマッチするパターンは有り得るが、通常は想定外の挙動
        $this->assertSame(0, $actual, 'このパターンは空文字列 "" とマッチします');
    }

    public function validRegExpProvider()
    {
        $ref = new \ReflectionClass(RegexPattern::class);

        foreach ($ref->getConstants() as $name => $value) {
            yield [$name, $value];
        }
    }
}

あとは、ReflectionClassConstantを活用すれば、さらにおもしろなDocTestに活用できておもしろいですよ(読者への課題とします)。このようなテスト方法についてはDocCommentでPHPのユニットテストの書きやすさを劇的に改善する手法 - pixiv inside [archive]に書きました。

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3