PHPUnit。 パート04テスト環境(フィクスチャ)

翻訳者の序文
この記事では、PHPUnit公式ドキュメントのロシア語への翻訳を続けています。
パート1パート2パート3



テスト環境のパラメーターの設定、つまりテスト世界の作成は、最も面倒な作業の1つです。 しかし、テストが完了したら、すべての変数を元の値に戻す必要があります-このタスクも簡単ではありません。 テスト環境またはテスト環境のパラメーターは、 -fixtureと呼ばれます。

例4.1では、テスト環境は$stack変数に格納された単純な配列でした。
ただし、ほとんどの場合、テスト環境ははるかに複雑であり、テスト環境で動作するコードの量はそれに応じて増加します。 テストの内容は、テスト環境での作業を担当するコードのノイズで失われる可能性があります。 同様のテスト環境を使用して複数のテストを作成すると、すべてが非常に悪くなります。 多数のコードの重複を取り除くには、テスト環境(フレームワーク)の助けが明らかに必要です。

PHPUnitは、テストセットアップコードの共有をサポートしています。
テストメソッドsetUp()する前setUp()テンプレートメソッドが呼び出されます。
テストメソッドが作業をtearDown()するとすぐに、別のテンプレートメソッドが呼び出されますtearDown()
さらに、その呼び出しは、テストが正常に完了したかどうかに依存しません。

例4.2では 、ソース/レシーバーアプローチを使用してテスト環境を共有しています。 しかし、これは常に受け入れられるわけではなく、多くの場合完全に不可能です。
例6.1は、テスト環境ではなく、それを作成するコードを再利用するような方法StackTestテストを作成する方法を示しています。
まず、メソッドのローカル変数の代わりに使用する$stackクラスの変数を宣言します。
その後、テスト環境の作成をsetUp()メソッドに移動します。
結論として、テストメソッドから既に不要になったコードを削除し、 $stackメソッドのローカル変数の代わりに新しいクラス変数$this->stack使用を開始し$stack

例6.1:setUp()を使用してスタックをテストするためのテスト環境を作成する
<?php<br>
class StackTest extends PHPUnit_Framework_TestCase<br>
{<br>
protected $stack;<br>
<br>
protected function setUp()<br>
{<br>
$ this ->stack = array();<br>
}<br>
<br>
public function testEmpty()<br>
{<br>
$ this ->assertTrue(empty($ this ->stack));<br>
}<br>
<br>
public function testPush()<br>
{<br>
array_push($ this ->stack, 'foo' );<br>
$ this ->assertEquals( 'foo' , $ this ->stack[count($ this ->stack)-1]);<br>
$ this ->assertFalse(empty($ this ->stack));<br>
}<br>
<br>
public function testPop()<br>
{<br>
array_push($ this ->stack, 'foo' );<br>
$ this ->assertEquals( 'foo' , array_pop($ this ->stack));<br>
$ this ->assertTrue(empty($ this ->stack));<br>
}<br>
}<br>
?>
<br>
<br>
* This source code was highlighted with Source Code Highlighter .


テンプレートメソッドsetUp()およびtearDown()は、テストクラスの各テストメソッド(および新しいインスタンス)に対して1回呼び出されます。

テンプレートメソッドsetUpBeforeClass()およびtearDownAfterClass()は、テストクラスの最初のメソッドが実行される前、および最後のメソッドが完了した後に呼び出されます。

次の例は、テストクラスで使用可能なすべてのテンプレートメソッドを示しています。

例6.2:この例は、可能なすべてのテンプレートメソッドのアプリケーションを示しています。
<?php<br>
require_once 'PHPUnit/Framework.php' ;<br>
<br>
class TemplateMethodsTest extends PHPUnit_Framework_TestCase<br>
{<br>
public static function setUpBeforeClass()<br>
{<br>
print __METHOD__ . "\n" ;<br>
}<br>
<br>
protected function setUp()<br>
{<br>
print __METHOD__ . "\n" ;<br>
}<br>
<br>
protected function assertPreConditions()<br>
{<br>
print __METHOD__ . "\n" ;<br>
}<br>
<br>
public function testOne()<br>
{<br>
print __METHOD__ . "\n" ;<br>
$ this ->assertTrue(TRUE);<br>
}<br>
<br>
public function testTwo()<br>
{<br>
print __METHOD__ . "\n" ;<br>
$ this ->assertTrue(FALSE);<br>
}<br>
<br>
protected function assertPostConditions()<br>
{<br>
print __METHOD__ . "\n" ;<br>
}<br>
<br>
protected function tearDown()<br>
{<br>
print __METHOD__ . "\n" ;<br>
}<br>
<br>
public static function tearDownAfterClass()<br>
{<br>
print __METHOD__ . "\n" ;<br>
}<br>
<br>
protected function onNotSuccessfulTest(Exception $e)<br>
{<br>
print __METHOD__ . "\n" ;<br>
throw $e;<br>
}<br>
}<br>
?>
<br>
<br>
* This source code was highlighted with Source Code Highlighter .


  phpunit TemplateMethodsTest
セバスチャン・バーグマンによるPHPUnit 3.4.2。

 TemplateMethodsTest :: setUpBeforeClass
 TemplateMethodsTest ::セットアップ
 TemplateMethodsTest :: assertPreConditions
 TemplateMethodsTest :: testOne
 TemplateMethodsTest :: assertPostConditions
 TemplateMethodsTest :: tearDown
 .TemplateMethodsTest :: setUp
 TemplateMethodsTest :: assertPreConditions
 TemplateMethodsTest :: testTwo
 TemplateMethodsTest :: tearDown
 TemplateMethodsTest :: onNotSuccessfulTest
 FTemplateMethodsTest :: tearDownAfterClass


時間:0秒

 1つの障害がありました。

 1)TemplateMethodsTest :: testTwo
 <boolean:false>がtrueであるとのアサートに失敗しました。
 /home/sb/TemplateMethodsTest.php:30

失敗!
テスト:2、アサーション:2、失敗:1。 



setUp()およびtearDown()を使用して練習する


setUp()tearDown()は理論的には完全に対称的である必要がありますが、実際にはそうではありません。
実際には、 setUp()でソケットやファイルなどの外部リソースを開いた場合は、必ずtearDown()呼び出す必要があります。 setUp()がPHPオブジェクトのみを作成する場合、 tearDown()は無視できます。 ただし、 setUp()で複数のオブジェクトが作成された場合、 tearDown()で作成されたオブジェクトにunset()呼び出しを行うのが妥当です。
したがって、 tearDown()はガベージコレクターの機能を実行します。
テストメソッドのオブジェクトのガベージコレクションは、実際には予測できません。

バリエーション


テスト環境がわずかに異なる2つのテストがある場合はどうなりますか? 次の2つのオプションが可能です。

テスト環境の共有


テスト環境を複数のテストと共有する理由はいくつかありますが、ほとんどの場合、この必要性はアプリケーションアーキテクチャの問題の結果です。

テスト環境を複数のテストと共有する良い例は、データベースへの接続です。 データベースへの接続は一度だけ確立され、テストごとに新しい接続を作成する代わりに、すべてのテストがこの接続を使用します。
この方法は、テストの実行を高速化するのに役立ちます。

例6.3は、 setUp()クラスのsetUp()およびtearDown()テンプレートメソッド( TestSuiteクラスの使用を参照)を使用して、テストスイートの最初のテストを実行し、最後のテスト後にデータベースから切断する前にデータベースに接続する方法を示しています。 $sharedFixtureオブジェクトの$sharedFixture属性は、 PHPUnit_Framework_TestSuiteおよびPHPUnit_Framework_TestCaseから継承されたすべてのクラスオブジェクトで使用できます。

例6.3:複数のテストスイートテストとテスト環境を共有する
<?php<br>
require_once 'PHPUnit/Framework.php' ;<br>
<br>
class DatabaseTestSuite extends PHPUnit_Framework_TestSuite<br>
{<br>
protected function setUp()<br>
{<br>
$ this ->sharedFixture = new PDO(<br>
'mysql:host=wopr;dbname=test' ,<br>
'root' ,<br>
'' <br>
);<br>
}<br>
<br>
protected function tearDown()<br>
{<br>
$ this ->sharedFixture = NULL;<br>
}<br>
}<br>
?>
<br>
<br>
* This source code was highlighted with Source Code Highlighter .


共有テスト環境を使用してテストの数を減らすことは驚くべきことです。
これは、アーキテクチャに隠れた問題があることを示している可能性があります-オブジェクトは不必要に相互接続されています。
最初にこの隠れた問題を解決し、その後にスタブを使用してテストを記述すると、結果が大幅に向上します( 第11章を参照)。 これは、テスト間に依存関係を作成し、アーキテクチャを改善する可能性を無視するよりもはるかに優れています。

グローバルステータス


シングルトンパターンを使用するコードをテストすることは非常に困難です (アプリケーションでクラスのインスタンスが1つだけ作成されます。したがって、グローバル変数の機能が実装されます。トランスレーターコメント)
このステートメントは、グローバル変数を適用する場合にも当てはまります。 多くの場合、テストするコードはグローバル変数に強く関連しており、その作成は制御できません。
別の問題は、1つのテストがグローバル変数の値を変更できるため、別のテストが中断されることです。

PHPでは、グローバル変数は次のように機能します。
グローバル変数に加えて、グローバル状態にはクラス属性も含まれます。
デフォルトでは、PHPUnitはグローバルおよびスーパーグローバル( $GLOBALS$_ENV$_POST$_GET$_COOKIE$_SERVER$_FILES$_REQUEST )を変更しても他のテストに影響を与えないようにテストを実行します。 さらに、この分離は静的クラス属性に拡張できます。

ご注意


静的クラス属性のバックアップおよび復元操作を使用するには、PHP 5.3以降が必要です。
グローバル変数および静的クラス属性のバックアップおよび復元操作では、 serialize()およびunserialize()関数を使用します。

PDOなど、PHPの一部である一部のクラスのオブジェクトは、保存および復元できません。
同様のオブジェクトを$GLOBALS配列に保存しようとすると失敗します。

グローバル変数の保存と復元は、 @backupGlobalsアノテーションを使用して制御できます。 @backupGlobals参照してください。
または、保存および復元操作で動作しない変数のリストを作成できます。以下のコードを参照してください。

 クラスMyTestはPHPUnit_Framework_TestCaseを拡張します
 {
     protected $ backupGlobalsBlacklist = array( 'globalVariable');

     // ...
 } 

ご注意


メソッド内で$backupGlobalsBlacklist属性を設定しても、たとえばsetUp()は効果がないことに注意してください。

静的属性の保存と復元は、 @backupStaticAttributesアノテーションを使用して制御できます。 @backupStaticAttributesを参照してください
または、保存および復元操作で動作しない静的属性のリストを作成できます。以下のコードを参照してください。

 クラスMyTestはPHPUnit_Framework_TestCaseを拡張します
 {
     protected $ backupStaticAttributesBlacklist = array(
       'className' =>配列( 'attributeName')
     );

     // ...
 } 

ご注意


メソッド内で$backupStaticAttributesBlacklist属性を設定しても、たとえばsetUp()は効果がないことに注意してください。

Source: https://habr.com/ru/post/J89581/


All Articles