前回、
今回取り上げるプログラム
今回取り上げるのは
#! /usr/local/bin/php
<?php
$url = "http://192.168.0.100/";
file_get_contents($url."?00=C");
file_get_contents($url."?01=D");
file_get_contents($url."?02=D");
file_get_contents($url."?03=C");
?>
どうでしょう。ちょっとテスト駆動に向かないのではないか、
こちらは、
#! /usr/local/bin/php
<?php
$url = "http://192.168.0.100/";
class rail {
var $number;
function rail($number = "00") {
$this->number = $number;
}
function drive($speed = 0) {
global $url;
if ($speed >= 0)
$command = substr("ABCDEF", min($speed, 5), 1);
else
$command = substr("abcdef", min(-$speed, 5), 1);
file_get_contents($url."?".$this->number."=".$command);
}
function sense() {
global $url;
return file_get_contents($url."?".$this->number."=S") + 0;
}
}
#
# |---r4---|---r3---|---r2---|---r1---|---r0---|
#
$r0 =& new rail("00");
$r1 =& new rail("01");
$r2 =& new rail("02");
$r3 =& new rail("03");
$r4 =& new rail("04");
for (;;) {
$r0->drive(2);
$r1->drive(3);
$r2->drive(3);
$r3->drive(2);
while ($r4->sense() == 0)
;
$r0->drive(0);
$r1->drive(0);
$r2->drive(0);
$r3->drive(0);
$r4->drive(-2);
$r3->drive(-3);
$r2->drive(-3);
$r1->drive(-2);
while ($r0->sense() == 0)
;
$r4->drive(0);
$r3->drive(0);
$r2->drive(0);
$r1->drive(0);
}
?>
今回使用するテストエンジンは、
#! /usr/local/bin/php
<?php
function asserteq($expected, $found) {
if ($expected === $found) {
printf(".");
return;
}
printf("\nexpected: \"%s\"\nfound: \"%s\"\n----\ntest failed.\n", $expected, $found);
die();
}
require(@$argv[1]);
foreach (get_declared_classes() as $classname) {
foreach (get_class_methods($classname) as $methodname) {
if (!ereg("^test", $methodname))
continue;
$obj =& new $classname();
$obj->$methodname();
}
}
print"\ntest successed.\n";
?>
また、
最初は1つのテストから
まず、
前回はテストをまとめて書きましたが、
#! /usr/local/bin/php
<?php
$url = "http://localhost/gh/rail/simrail.php5";
class rail {
}
class testrail extends rail {
function test1() {
$obj =& new testrail();
asserteq("00", $obj->number);
}
}
if (function_exists("asserteq"))
return;
#
# |---r4---|---r3---|---r2---|---r1---|---r0---|
#
$r0 =& new rail("00");
〈以下省略〉
実行すると、
では、
class rail {
var $number = "00";
}
「ふざけてるんじゃないか」
ちなみに、
$ php run.php rail21.php . test successed. $
さすがに、
$obj =& new testrail("12");
asserteq("12", $obj->number);
このテストを通すためのコードを書きます。やっと、
class rail {
var $number;
function rail($number = "00") {
$this->number = $number;
}
}
次はdrive()メソッドですが、
そこでgethttp()というメソッドを用意し、
これも、
#! /usr/local/bin/php
<?php
$url = "http://localhost/gh/rail/simrail.php5";
class rail {
var $number;
function rail($number = "00") {
$this->number = $number;
}
}
class testrail extends rail {
function test1() {
$obj =& new testrail();
asserteq("00", $obj->number);
$obj =& new testrail("12");
asserteq("12", $obj->number);
$obj->gethttp("http://a.b/");
asserteq("http://a.b/", $obj->gethttpurl);
}
}
if (function_exists("asserteq"))
return;
#
# |---r4---|---r3---|---r2---|---r1---|---r0---|
#
$r0 =& new rail("00");
〈以下省略〉
テストを通すためのコードを書きます。
var $gethttpurl;
function gethttp($url) {
$this->gethttpurl = $url;
}
ちなみに、
本来のrailクラスにもgethttp()メソッドを作り、
function gethttp($url) {
return file_get_contents($url);
}
では、
#! /usr/local/bin/php
<?php
$url = "http://localhost/gh/rail/simrail.php5";
class rail {
var $number;
function rail($number = "00") {
$this->number = $number;
}
function gethttp($url) {
return file_get_contents($url);
}
}
class testrail extends rail {
var $gethttpurl;
function gethttp($url) {
$this->gethttpurl = $url;
}
function test1() {
$obj =& new testrail();
asserteq("00", $obj->number);
$obj =& new testrail("12");
asserteq("12", $obj->number);
$obj->gethttp("http://a.b/");
asserteq("http://a.b/", $obj->gethttpurl);
$obj =& new testrail("34");
$obj->drive();
asserteq("http://a.b/?34=A", $obj->gethttpurl);
}
}
if (function_exists("asserteq"))
return;
#
# |---r4---|---r3---|---r2---|---r1---|---r0---|
#
$r0 =& new rail("00");
〈以下省略〉
コード本体も、
function drive() {
$this->gethttp("http://a.b/?34=A");
}
次のテストでは、
$obj =& new testrail("56");
$obj->drive();
asserteq("http://a.b/?56=A", $obj->gethttpurl);
そしてコードでは、
function drive($speed = 0) {
$this->gethttp("http://a.b/?{$this->number}=A");
}
今度はメソッドのパラメータです。これも、
$obj->drive(1);
asserteq("http://a.b/?56=B", $obj->gethttpurl);
コードが追いかけます。
function drive($speed = 0) {
$command = substr("ABCDEF", $speed, 1);
$this->gethttp("{$this->baseurl}?{$this->number}={$command}");
}
ところで、
この作業については、
#! /usr/local/bin/php
<?php
$url = "http://localhost/gh/rail/simrail.php5";
class rail {
var $baseurl;
var $number;
function rail($number = "00") {
global $url;
$this->baseurl = $url;
$this->number = $number;
}
function gethttp($url) {
return file_get_contents($url);
}
function drive($speed = 0) {
$command = substr("ABCDEF", $speed, 1);
$this->gethttp("{$this->baseurl}?{$this->number}={$command}");
}
}
class testrail extends rail {
var $gethttpurl;
function testrail($number = "00") {
parent::rail($number);
$this->baseurl = "http://a.b/";
}
function gethttp($url) {
$this->gethttpurl = $url;
}
function test1() {
$obj =& new testrail();
asserteq("00", $obj->number);
$obj =& new testrail("12");
asserteq("12", $obj->number);
$obj->gethttp("http://a.b/");
asserteq("http://a.b/", $obj->gethttpurl);
$obj =& new testrail("34");
$obj->drive();
asserteq("http://a.b/?34=A", $obj->gethttpurl);
$obj =& new testrail("56");
$obj->drive();
asserteq("http://a.b/?56=A", $obj->gethttpurl);
$obj->drive(0);
asserteq("http://a.b/?56=A", $obj->gethttpurl);
$obj->drive(1);
asserteq("http://a.b/?56=B", $obj->gethttpurl);
$obj->drive(5);
asserteq("http://a.b/?56=F", $obj->gethttpurl);
}
}
if (function_exists("asserteq"))
return;
#
# |---r4---|---r3---|---r2---|---r1---|---r0---|
#
$r0 =& new rail("00");
〈以下省略〉
続いて、
$obj->drive(6);
asserteq("http://a.b/?56=F", $obj->gethttpurl);
そして、
function drive($speed = 0) {
$command = substr("ABCDEF", min($speed, 5), 1);
$this->gethttp("{$this->baseurl}?{$this->number}={$command}");
}
この続きは宿題にするとして、
テスト駆動開発はなぜ直感に反することをするのか
ここまでの流れで、
まず
1つ利点として言えるのは、
ほかにも、
これらのやり方は、
$obj =& new testrail();
asserteq("00", $obj->number);
$obj =& new testrail("12");
asserteq("12", $obj->number);
最初の2つのテストは、
$obj->gethttp("http://a.b/");
asserteq("http://a.b/", $obj->gethttpurl);
次はgethttp()ですが、
var $gethttpurl;
function testrail($number = "00") {
parent::rail($number);
$this->baseurl = "http://a.b/";
}
function gethttp($url) {
$this->gethttpurl = $url;
}
テスト用に"http://
$obj =& new testrail("34");
$obj->drive();
asserteq("http://a.b/?34=A", $obj->gethttpurl);
drive()メソッドも、
つまり、
テスト駆動開発に向かないもの
冒頭に
筆者は、
1つめは
2つめは
3つめは
リスト1の場合、
テストの保守性については、