cli で起動する PHP スクリプトで、次のように標準入力を取得し処理するものがあります。
<?php
class Foo
{
function main()
{
$stdin_data = file_get_contents("php://stdin");
if (preg_match("/regex/", $stdin_data)) {
return true;
} else {
return false;
}
}
}
?>
これの単体試験を行うため、テストケースを作りたいと思っています。
そのためテストケース中で、上述したスクリプト中の $stdin_data という変数に任意のデータを入れたいのですが、標準入力ストリームを上書きする方法がわかりません。
$stdin_data に任意のデータを入れる方法を教えてください。
どちらもclass Fooを若干変更する必要があるのですが、こんな感じでいかがでしょう?
<?php class Foo { function main($filename = "php://stdin") { if($filename != "php://stdin") { print "WARNING: filename = ($filename)\n"; } $stdin_data = file_get_contents($filename); if (preg_match("/regex/", $stdin_data)) { return true; } else { return false; } } } $foo =& new Foo(); $result = $foo->main("./case1.txt"); print "case1 = ($result)\n"; $result = $foo->main("./case2.txt"); print "case2 = ($result)\n"; ?>
<?php $MY_STDIN = "php://stdin"; function my_file_get_contents() { global $MY_STDIN; if($MY_STDIN != "php://stdin") { print "WARNING: MY_STDIN = ($MY_STDIN)\n"; } return file_get_contents($MY_STDIN); } class Foo { function main() { $stdin_data = my_file_get_contents(); if (preg_match("/regex/", $stdin_data)) { return true; } else { return false; } } } $foo =& new Foo(); $MY_STDIN = "./case1.txt"; $result = $foo->main(); print "case1 = ($result)\n"; $MY_STDIN = "./case2.txt"; $result = $foo->main(); print "case2 = ($result)\n"; ?>
状況がよく分からないのですが、テストデータをファイル (test.dat など) で用意しておいて、
php hoge.php < test.dat
のようにリダイレクトで渡すのではどうでしょうか。
PHPUnit や SimpleTest を利用し、テストケースは PHP だけで簡潔させたいと思っているため、シェルのリダイレクトを利用することができません。
次の様なテストケースを書きたいです。
(これだと file_put_contents のところで失敗するんですけど、やりたいことは分かると思います。)
class FooTestCase extends SimpleTest
{
var $Foo = null;
class __construct()
{
$this->Foo =& new Foo();
}
class main()
{
file_put_contents("php://stdin", "hogehoge\nregex\n");
$result = $this->Foo->main();
$this->assertTrue($result);
}
}
?>
いろいろ試しましたが、難しいですね。
同じようなことをやろうとした人がいます、
http://d.hatena.ne.jp/heavenshell/20090129/1233230514
知ってるのかもだが、phptというテストフレームワークもあるんすね。
レシピファイルみたいなとこに
として記述してやれば良いみたい。
これも純粋なphpの記述じゃないからダメなんすかね?
ま、シェル書くのと何が違うのって言われりゃ、シェルよりはphpと親和性高いんじゃないのくらいだけど。
phpt というものがあるんですね!!
組み込んでいけるかもしれません!!
試してみます!!
どちらもclass Fooを若干変更する必要があるのですが、こんな感じでいかがでしょう?
<?php class Foo { function main($filename = "php://stdin") { if($filename != "php://stdin") { print "WARNING: filename = ($filename)\n"; } $stdin_data = file_get_contents($filename); if (preg_match("/regex/", $stdin_data)) { return true; } else { return false; } } } $foo =& new Foo(); $result = $foo->main("./case1.txt"); print "case1 = ($result)\n"; $result = $foo->main("./case2.txt"); print "case2 = ($result)\n"; ?>
<?php $MY_STDIN = "php://stdin"; function my_file_get_contents() { global $MY_STDIN; if($MY_STDIN != "php://stdin") { print "WARNING: MY_STDIN = ($MY_STDIN)\n"; } return file_get_contents($MY_STDIN); } class Foo { function main() { $stdin_data = my_file_get_contents(); if (preg_match("/regex/", $stdin_data)) { return true; } else { return false; } } } $foo =& new Foo(); $MY_STDIN = "./case1.txt"; $result = $foo->main(); print "case1 = ($result)\n"; $MY_STDIN = "./case2.txt"; $result = $foo->main(); print "case2 = ($result)\n"; ?>
実はテスト対象のクラス(Foo)の入力部分を変更してしまうということも少し考えていました。
しかし上手く動かすアイデアが思いつかなかったことと、元クラスに手を入れるのに少し勇気が要るので、まずはテストケースだけで完結できないかと考えていました!!
どうしても完結できなかったら、この方法で試してみたいと思います!!
ありがとうございます!!
実はテスト対象のクラス(Foo)の入力部分を変更してしまうということも少し考えていました。
しかし上手く動かすアイデアが思いつかなかったことと、元クラスに手を入れるのに少し勇気が要るので、まずはテストケースだけで完結できないかと考えていました!!
どうしても完結できなかったら、この方法で試してみたいと思います!!
ありがとうございます!!