web-dev-qa-db-ja.com

PHPUnitは実際の例をテストします

mail ラッパークラスを作成しました。電子メールを送信するライブラリがたくさんあることは知っていますが、TDDを学びたいと思っています...そこで、いくつかのテストを作成し、いくつかのコードを用意しました。これで、コンストラクターに電子メールアドレスを設定して検証できます...電子メールアドレスが間違っていると、例外が発生します。必須フィールドはメールアドレスだけです...ユーザーがコンストラクターですべてのメールデータを設定するため、セットと取得はありません。

次に、送信テストを作成します。どうやって始めたらいいのかわからない。セッターとゲッターが必要ない場合、値(件名、メール本文、ヘッダー)が存在するかどうかをテストするにはどうすればよいですか?メールを送信できるかどうかをテストするにはどうすればよいですか?

実世界のTDDの例は私には難しいです。私はそれについて学ぼうとしました、私はたくさんのことを読みました、しかし私は実際のコードをテストすることができません。

ありがとう。

19
thom

メール関数にリンクしているため、mailの呼び出しはコードにハードコードされている可能性があります。だから見てください

testhelper extension をインストールし、mailへの呼び出しをモックします。次に、ラッパーのsendメソッドが呼び出されたときに、モックが正しい値で呼び出されたことを検証します。どこかにカスタムメール関数を定義します。

_function mail_mock()
{
    $allThatWasPassedToTheFunction = func_get_args();
    return $allThatWasPassedToTheFunction;
}
_

次に、send()テストで、次のようなことを行います。

_public function testSendReceivesExpectedValues()
{
    // replace hardcoded call to mail() with mock function
    rename_function('mail', 'mail_orig');
    rename_function('mail_mock', 'mail');

    // use the wrapper
    $testClass = new MailWrapper('[email protected]');
    $results = $testClass->send();

    // assert the result
    $this->assertSame('[email protected]', $results[0]);
    $this->assertSame('Default Title', $results[1]);
    $this->assertSame('Default Message', $results[2]);
}
_

上記は、send関数がmail()呼び出しの結果を返すことを前提としていることに注意してください。

一般に、sendmail、データベース、ファイルシステムなどの外部サブシステムを常に モックまたはスタブ に置き換えようとするため、外部サブシステムとは別に独自のコードのテストに集中できます。 。 mailが実際に機能することをテストする必要はありません。

http://www.phpunit.de/manual/3.6/en/test-doubles.html も参照してください。

16
Gordon

純粋な単体テストでは、実際の電子メールが送信されたかどうかを実際にテストするのではなく、適切なプログラミングユニット(この場合はmail関数)が呼び出されたかどうかをテストします。 mail関数が実際に機能するかどうかをテストする方法がよくわかりません。これは、電子メールが内部でどのように機能するかについての深い知識がないためです。だから、私はユニットテストをどのように行うかを書くだけです。

クラスコンストラクターにオプションの引数を受け入れさせることができます。これは、実際に電子メールを送信する実際の作業を行う関数です。デフォルトでは、これはmail関数になりますが、テストセットアップでは、正しいサブジェクト、本文、およびヘッダーが存在することを実際にチェックする特別な関数を提供します。

テスト:

<?php

class EmailerTest extends PHPUnit_Framework_TestCase
{
  public function testMailFunctionIsCalledWithCorrectArguments()
  {
    $actualSubject, $actualBody, $actualHeaders;
    $mailFunction = function ($subject, $body, $headers)
        use (&$actualSubject, &$actualBody, &$actualHeaders) {
      $actualSubject = $subject;
      $actualBody = $body;
      $actualHeaders = $headers;
    };

    $emailer = new Emailer($options, $mailFunction);
    $emailer->send();

    $this->assertEquals('Expected subject', $actualSubject);
    $this->assertEquals('Expected body', $actualBody);
    $this->assertEquals('Expected headers', $actualHeaders);
  }
}

そして、テスト中のクラス:

<?php

class Emailer
{
  public function __construct($options, $mailFunction = 'mail')
  {
    $this->subject = $options->subject;
    $this->body = $options->body;
    // etc.
    $this->mailFunction = $mailFunction;
  }

  public function send()
  {
    // find out $subject, $body, $headers, and then...

    call_user_func_array($this->mailFunction, array(
      $subject,
      $body,
      $headers
    ));
  }
}

いくつかの値を完了または実装するために残しているため、これはある種の擬似コードです。重要な点は、テストしているクラスの共同作業者にテストダブルを提供する必要があるということです。

この場合、それは単なる関数です(私はいくつかのPHP 5.3)機能を利用しましたが、テスト対象のクラスに渡すオブジェクトインスタンスである可能性があります。

2
Ionuț G. Stan

クラスは電子メール、件名、その他の情報の検証を実行する必要があると思うので、これを関数に分離することをお勧めします。

特定の結果を返さなければならないプライベート検証関数がある場合は、それをテストするためのアサーションを作成できます。

この記事 役に立つかもしれません。

私もTDDに非常に慣れていないので、このプロセスを理解するためにIDE(Netbeans)に依存することにしました。

この助けを願っています:)

0
Panuwizzle