PHPUnit3で始めるユニットテスト

第2回 ショッピングカートクラスを作ってみる(1)

この記事を読むのに必要な時間:およそ 7 分

3番目の仕様「数量を変更する場合,商品コードと変更する数量(整数)を指定する」

続いて,3番目の仕様

数量を変更する場合,商品コードと変更する数量(整数)を指定する

です。よく考えてみると,2番目の仕様で実装した内容と今回実装しようとしている内容は「商品コードと数量を指定してカートの中身を変更する」ことに変わりありません。1つのメソッドに統一できそうですね。今回はaddメソッドを変更することで,3番目の仕様を実装する事にしましょう。それでは今までと同様,仕様に対するテストを考えてみます。

  • 変更するためのメソッドにコードと任意の整数を渡すと,trueを返す
  • 変更するためのメソッドにコードと非数を渡すと,例外UnexpectedValueException((OutOfBoundsExceptionと同様,SPLで定義されている例外))を投げる

これがaddメソッドの新しい仕様となります。まずは,addメソッドの実装で用意したテストを修正しましょう。

<?php
require_once 'PHPUnit/Framework.php';
require_once 'Cart.php';

class CartTest extends PHPUnit_Framework_TestCase
{
    public function testInitCart() {
        $cart = new Cart();
        $this->assertTrue(is_array($cart->getItems()));
        $this->assertEquals(0, count($cart->getItems()));
    }

    public function testAdd() {
        $cart = new Cart();
        $this->assertTrue($cart->add('001', 1));
        $this->assertTrue($cart->add('001', 0));
        $this->assertTrue($cart->add('001', -1));
    }

    public function testAddNotNumeric() {
        $cart = new Cart();
        try {
            $cart->add('001', 'string');
        } catch (UnexpectedValueException $e) {
            return;
        }
        $this->fail();
    }

    public function testAddFloat() {
        $cart = new Cart();
        try {
            $cart->add('001', 1.5);
        } catch (UnexpectedValueException $e) {
            return;
        }
        $this->fail();
    }
}

随分スッキリしてしまいました。それでは,phpunitコマンドを実行して,テスト結果を確認しておきましょう。

$ phpunit CartTest
PHPUnit 3.1.7 by Sebastian Bergmann.

.EEE

Time: 0 seconds

There were 3 errors:

1) testAdd(CartTest)
OutOfBoundsException: Invalid amount
/home/shimooka/public_html/gihyo.jp/CartTest.php:16

2) testAddNotNumeric(CartTest)
OutOfBoundsException: Invalid amount
/home/shimooka/public_html/gihyo.jp/CartTest.php:23

3) testAddFloat(CartTest)
OutOfBoundsException: Invalid amount
/home/shimooka/public_html/gihyo.jp/CartTest.php:33

FAILURES!
Tests: 4, Errors: 3.
$ 

3箇所でエラーが発生するようになりました。16行目は,数量に0を指定できるかどうかのテストで,今回仕様変更になった箇所です。23行目と33行目は投げられる例外が変更になったことが原因です。それでは,Cartクラスを変更します。

<?php
class Cart
{
    public function getItems() {
        return array();
    }

    public function add($item_cd, $amount) {
        if (preg_match('/^\d+$/', $amount) && (int)$amount >= 0) {
            return true;
        } else {
            throw new UnexpectedValueException('Invalid amount');
        }
    }
}
$ phpunit CartTest
PHPUnit 3.1.7 by Sebastian Bergmann.

.E..

Time: 0 seconds

There was 1 error:

1) testAdd(CartTest)
UnexpectedValueException: Invalid amount
/home/shimooka/public_html/gihyo.jp/CartTest.php:17

FAILURES!
Tests: 4, Errors: 1.
$ 

今度はCartTest.phpの17行目にある数量に負数を指定した場合のテストで失敗しています。同様に修正します。

<?php
class Cart
{
    public function getItems() {
        return array();
    }

    public function add($item_cd, $amount) {
        if (preg_match('/^-?\d+$/', $amount)) {
            return true;
        } else {
            throw new UnexpectedValueException('Invalid amount');
        }
    }
}
$ phpunit CartTest
PHPUnit 3.1.7 by Sebastian Bergmann.

....

Time: 0 seconds


OK (4 tests)
$ 

テストに通りました。こちらも随分コードがスッキリしましたね。これで3番目の仕様の実装も完了としましょう。

次回は,残りの3つの仕様をテストを作りながら実装していきます。

著者プロフィール

下岡秀幸(しもおかひでゆき)

PHP関連の情報サイト「Do You PHP?」の管理人。PHP歴は長いが,あまり仕事で使ったことがないという噂がある。最近はα版のPEAR・PECLに手を出しては地雷を踏んでいることが多い。

URLhttp://www.doyouphp.jp/http://d.hatena.ne.jp/shimooka/