【PHPUnit簡単サンプル付き】単体テストとは?

zax_developerTest

はじめまして、ザックス株式会社の開発担当のものです。
今回は、ソフトウェアテストの工程の1つ『単体テスト』について触れていきたいと思います。

ソースコードの個々のユニット、すなわち、1つ以上のコンピュータプログラムモジュールが使用に適しているかどうかを決定するために、関連する制御データ、使用手順、操作手順とともにテストする手法である。フリー百科事典『ウィキペディア(Wikipedia)』単体テストより

目次

  1. はじめに
  2. 計算プログラム、テストプログラムの用意
  3. テストプログラムの修正、実行(結果はRED)
  4. 計算プログラムの修正、テストプログラムを実行(結果はGREEN)
  5. 要件の変更によるテストプログラムの修正、実行(結果はRED)
  6. 計算プログラムを修正、テストプログラムを実行(結果はGREEN)
  7. 最後に

1.はじめに

基本的なシステムの開発は、個々のプログラム処理がきちんと動作するかテストをしながら進めていきます。
今回はPHPプログラムでの開発を想定し、PHPUnitという単体テスト専用のフレームワークを使用した簡単な例での説明を行いたいと思います。
※PHPのインストール及びPHPUnitが動作する環境の準備が済んでいることが前提になります。

作業環境/利用ツール
xampp for OS X 7.2.25
PHP 7.2.25
PHPUnit 8.5.0
composer 1.9.1
テストプログラムの配置ディレクトリ /test
テスト対象プログラムの配置ディレクトリ /src

2.計算プログラム、テストプログラムの用意

長方形の面積を求める単純なプログラムを用意します。
長方形の面積を求める計算プログラムを「Cal.php」、計算プログラムが正しく意図したとおりに動作したことをテストするプログラムを「CalTest.php」とします。

/src/Cal.php
<?php

namespace App;

class Cal
{
    public function rectangle()
	{
	}
}
/test/CalTest.php
<?php

use PHPUnit\Framework\TestCase;
use App\Cal;

class CalTest extends TestCase
{
    public function testReturnRectangle()
	{
	}
}

3.テストプログラムの修正、実行(結果はRED)

テストファーストに基づいて、テストプログラムに長方形の面積が正しく求められているかどうかを確認するテストコードを追加します。
長方形の面積を求める式は、縦の長さx横の長さになります。
縦の長さが4、横の長さを5と仮定すると、期待される値は20ということになります。

/test/CalTest.php
<?php

use PHPUnit\Framework\TestCase;
use App\Cal;

class CalTest extends TestCase
{
    public function testReturnRectangle()
	{
	    $cal = new Cal;
		$this->assertEquals(20, $cal->rectangle(4, 5));
	}
}

テストを実行すると、まだ計算プログラムにロジックを追加していないため、テストが失敗します。

$ ./vendor/bin/phpunit
PHPUnit 8.5.0 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.2.25
Configuration: /opt/lampp/htdocs/project/phpunit.xml

F                                                                   1 / 1 (100%)

Time: 19 ms, Memory: 4.00 MB

There was 1 failure:

1) CalTest::testReturnRectangle
Failed asserting that null matches expected 20.

/opt/lampp/htdocs/project/test/CalTest.php:13

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

4.計算プログラムの修正、テストプログラムを実行(結果はGREEN)

テスト失敗(RED)からテスト成功(GREEN)にするために、計算プログラムにロジックを追加します。
再度テストを実行すると、テストが成功するようになります。

/src/Cal.php
<?php

namespace App;

class Cal
{
    public function rectangle($a, $b)
	{
	    return $a * $b;
	}
}
$ ./vendor/bin/phpunit
PHPUnit 8.5.0 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.2.25
Configuration: /opt/lampp/htdocs/project/phpunit.xml

.                                                                   1 / 1 (100%)

Time: 17 ms, Memory: 4.00 MB

OK (1 test, 1 assertion)

5.要件の変更によるテストプログラムの修正、実行(結果はRED)

次に長方形の面積ではなく、体積を求めるようにしてほしいと要件に変更があったとします。
直方体の体積を求めるように、テストプログラムを修正します。
直方体の体積は、縦の長さx横の長さx高さになります。
縦の長さが4、横の長さを5、高さを7と仮定すると、期待される値は140ということになります。
テストを実行し、失敗することを確認します。

/test/CalTest.php
<?php

use PHPUnit\Framework\TestCase;
use App\Cal;

class CalTest extends TestCase
{
	public function testReturnRectangular()
	{
	    $cal = new Cal;
		$this->assertEquals(140, $cal->rectangular(4, 5, 7));
	}
}
$ ./vendor/bin/phpunit
PHPUnit 8.5.0 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.2.25
Configuration: /opt/lampp/htdocs/project/phpunit.xml

E                                                                   1 / 1 (100%)

Time: 18 ms, Memory: 4.00 MB

There was 1 error:

1) CalTest::testReturnRectangular
Error: Call to undefined method App\Cal::rectangular()

/opt/lampp/htdocs/project/test/CalTest.php:11

ERRORS!
Tests: 1, Assertions: 0, Errors: 1.

6.計算プログラムを修正、テストプログラムを実行(結果はGREEN)

計算プラグラムを修正し、テストを実行します。

/src/Cal.php
<?php

namespace App;

class Cal
{
	public function rectangular($a, $b, $c)
	{
	    return $a * $b * $c;
	}
}
$ ./vendor/bin/phpunit
PHPUnit 8.5.0 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.2.25
Configuration: /opt/lampp/htdocs/project/phpunit.xml

.                                                                   1 / 1 (100%)

Time: 17 ms, Memory: 4.00 MB

OK (1 test, 1 assertion)

テストが問題なく成功していることが確認できました。

7.最後に

単体テストについて、簡単なサンプルを用いて説明してきました。
以下、思いつく限りのメリットを箇条書きで記載します。

  • 一度テストコードを実装しておくと、要件の変更や追加等があった場合、他の処理に影響があるか自動的に確認ができる。
    ※例えばCI環境を構築し、開発者がプログラムを特定の場所にコミットするたびに、単体テストを自動で実行するようにするなど。
  • テストから先に実装するため、オブジェクト指向のプログラミング開発を行うことができる。
    ※オブジェクト指向のプログラムでないと、後から単体テストを組み込む場合、設計の段階からやり直す必要がでてくる。

弊社では、単体テスト、結合テスト、性能テスト、セキュリティテストについて一貫したテスティングサービスを行なっています。
まずは、お気軽にお問い合わせください。