ホームページ  >  記事  >  バックエンド開発  >  phpUnit を使用した TDD 入門

phpUnit を使用した TDD 入門

WBOY
WBOYオリジナル
2016-08-08 09:29:491417ブラウズ

phpunitを使ってTDDシリーズを実践してみる

銀行口座から始めましょう

phpunit がインストールされていると仮定します。

TDD (テスト駆動開発) の考え方を理解するために、簡単な銀行口座の例から始めます。

プロジェクト ディレクトリの下に 2 つのディレクトリ srctest,在src下建立文件 BankAccount.php,在test目录下建立文件BankAccountTest.php を作成します。

TDD の考え方によれば、最初にテストを書いてから本番コードを書くので、BankAccount.php留空,我们先写BankAccountTest.php

リーリー

それでは、実行して結果を見てみましょう。 phpunit を実行するコマンドラインは次のとおりです:

リーリー

--bootstrap src/BankAccount.php是说在运行测试代码之前先加载 src/BankAccount.php,要运行的测试代码是test/BankAccountTest.php

特定のテストファイルを指定せずにディレクトリのみを指定した場合、phpunitは*Test.php 的文件。因为test目录下只有BankAccountTest.phpファイルと名前が一致するディレクトリ内のすべてのファイルを実行するため、

を実行します リーリー

同じ結果が得られます。

リーリー

テストがないため、警告エラーが発生します。

アカウントのインスタンス化

以下にテストを追加してみましょう。 TDD は、モジュールの機能をボトムアップで設計するのに役立つ設計手法であることに注意してください。テストを書くときは、ユーザーの視点から始めなければなりません。ユーザーが BankAccount クラスを使用する場合、最初に何をしますか? BankAccount の新しいインスタンスである必要があります。したがって、最初のテストは インスタンス化 のテストです。

リーリー

phpunit の実行が予想どおり失敗しました。

リーリー

クラスの定義が見つかりませんでした。次に、本番コードを記述します。テストに合格させます。 src/BankAccount.php (以下、ソースファイルと呼びます) に次の内容を入力します: BankAccount类的定义,下面我们就要写生产代码。使测试通过。在src/BankAccount.php リーリー

phpunitを実行するとテストに合格します。

リーリー

次に、テストを追加してテストを失敗させる必要があります。新規口座を作成した場合、口座残高は0になります。そこで、

ステートメントを追加しました: assert リーリー

value()

のメンバー関数であることに注意してください。もちろん、この関数はまだ定義されていません。ユーザーとしては、value()BankAccount的一个成员函数,当然这个函数还没有定义,作为使用者我们希望BankAccount がこの関数を提供することを望んでいます。

phpunitを実行すると、結果は次のようになります:

リーリー

結果は、BankAccount并没有value() にメンバー関数 value() がないことがわかります。プロダクションコードを追加:

リーリー

なぜ value()直接返回0,因为测试代码中希望value() は 0 を返す必要があるのでしょうか? TDD の原則は、テストに合格できる程度の冗長な製品コードを作成しないことです。

口座の入出金

phpunit を実行して渡した後、まず BankAccount的实例化已经满足要求了,接下来,用户希望怎么使用BankAccount呢?一定希望往里面存钱,嗯,希望BankAccount のインスタンス化が要件を満たしていると仮定します。次に、ユーザーは

をどのように使用したいですか?ぜひ入金したいのですが、この関数を呼び出すことで口座残高を増やすことができるといいのですが。そこで、次のテストを追加します。

リーリー

口座の初期残高は0です。10元入金した場合、口座残高は当然10になります。 phpunit を実行すると、デポジット関数がまだ定義されていないため、テストは失敗します。

リーリー

次にソースファイルにデポジット関数を追加します:

リーリー

phpunit を再度実行すると、次の結果が得られます:

リーリー

この時、入金機能で口座残高の操作を行っていないため、残高の初期値は0であり、入金機能実行後も0のままとなり、ユーザーが期待する動作ではありません。ユーザーが入金した金額を残高に追加する必要があります。

$value,那么value函数应该返回$value残高を操作するには、残高をBankAccountのメンバー変数にする必要があります。この変数は外部から変更できないため、プライベート変数として定義されます。次に、プライベート変数

の値を製品コードに追加します。

リーリー deposit函数传递负数,就相当于取钱了。
于是我们在测试代码的testDepositphpunitを実行するとテストに合格します。次に、ユーザーが他に何を必要としているのかを考えました。はい、お金を引き出します。お金を引き出すとき、この金額は口座残高から差し引かれます。

関数に 2 行のコードを追加するとします。

リーリー

phpunitを再度実行すると、テストが失敗しました。

リーリー $valueこれは、製品コードでは単に

を結果 10 に設定しているためです。実稼働コードを改善します。

リーリー

phpunitを再度実行すると、テストに合格します。

新しいコンストラクター

BankAccount对象时,可以传入一个值作为账户余额。于是我们在testNewAccount 次に、ユーザーは

オブジェクトの作成時にアカウント残高として値を渡すことができる別のコンストラクターが必要になる可能性があることに気づきました。そこで、このインスタンス化テストを testNewAccount に追加します。

リーリー

phpunitを実行すると、結果は次のようになります: 🎜
<code>1) BankAccountTest::testNewAccount
Failed asserting that null matches expected 10.</code>

这时因为BankAccount没有带参数的构造函数,因此new BankAccount(10)会返回一个空对象,空对象的value()函数自然返回的也是null。为了通过测试,我们在生产代码中增加带参数的构造函数。

<code>public function __construct($n){
    $this->value = $n;
}</code>

再运行测试:

<code>1) BankAccountTest::testNewAccount
Missing argument 1 for BankAccount::__construct(), called in /home/wuchen/projects/jolly-code-snippets/php/phpunit/test/BankAccountTest.php on line 5 and defined

/home/wuchen/projects/jolly-code-snippets/php/phpunit/src/BankAccount.php:5
/home/wuchen/projects/jolly-code-snippets/php/phpunit/test/BankAccountTest.php:5

2) BankAccountTest::testDeposit
Missing argument 1 for BankAccount::__construct(), called in /home/wuchen/projects/jolly-code-snippets/php/phpunit/test/BankAccountTest.php on line 12 and defined

/home/wuchen/projects/jolly-code-snippets/php/phpunit/src/BankAccount.php:5
/home/wuchen/projects/jolly-code-snippets/php/phpunit/test/BankAccountTest.php:12</code>

两个调用new BankAccount()的地方都报告了错误,增加了带参数的构造函数,不带参数的构造函数又不行了。从c++/java过渡来的同学马上想到增加一个默认的构造函数:

<code>public function __construct() {
    $this->value = 0;
}</code>

但这样是不行的,因为php不支持函数重载,所以不能有多个构造函数。

怎么办?对了,我们可以为参数增加默认值。修改构造函数为:

<code>public function __construct($n = 0){
    $this->value = $n;
}</code>

这样调用 new BankAccount()时,相当于传递了0给构造函数,满足了需求。
phpunit运行以下,测试通过。

这时,我们的生产代码为:

<code><?php
class BankAccount {
    private $value;             // default to 0

    public function __construct($n = 0){
        $this->value = $n;
    }
    
    public function value(){
        return $this->value;
    }

    public function deposit($ammount) {
        $this->value += $ammount;
    }
}
?></code>

总结

虽然我们的代码并不多,但是每一步都写得很有信心,这就是TDD的好处。即使你对php的语法不是很有把握(比如我),也可以对自己的代码很有信心。

用TDD的方式写程序的另一个好处,就是编码之前不需要对单个模块进行仔细的设计,可以在写测试的时候进行设计。这样开发出来的模块既可以满足用户需要,也不会冗余。

后面将会介绍 phpunit 的更多用法。

以上就介绍了用phpUnit入门TDD,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。