PHPUnit тестирует реальный пример - PullRequest
19 голосов
/ 14 июня 2011

Я создал mail класс оболочки. Я знаю, что есть много библиотек для отправки электронных писем, но я хочу изучить TDD ... Итак, я создал несколько тестов и у меня есть код. Теперь я могу установить адрес электронной почты в конструкторе и проверить его ... если адрес электронной почты неправильный, возникает исключение. Адрес электронной почты является единственным обязательным полем ... У меня нет наборов и получателей, потому что пользователь настроит все данные электронной почты на конструкторе.

Теперь я собираюсь написать тесты для отправки. Я не знаю с чего начать. Как я могу проверить, есть ли значения (тема, тело письма, заголовки), если я не хочу иметь установщики и получатели? Как я могу проверить, можно ли отправить электронное письмо?

Примеры реального TDD для меня трудны. Я пытался узнать об этом, я прочитал много вещей, но я не могу проверить реальный код.

Спасибо.

Ответы [ 3 ]

16 голосов
/ 14 июня 2011

Поскольку вы связались с почтовой функцией, вызов mail, вероятно, жестко запрограммирован в вашем коде. Итак, посмотрите на

Установите расширение testhelper и смоделируйте вызов 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('foo@example.com');
    $results = $testClass->send();

    // assert the result
    $this->assertSame('foo@example.com', $results[0]);
    $this->assertSame('Default Title', $results[1]);
    $this->assertSame('Default Message', $results[2]);
}

Обратите внимание, что вышеизложенное предполагает, что ваша функция отправки будет возвращать результат вызова mail().

Как правило, вы всегда будете пытаться заменить внешнюю подсистему, такую ​​как sendmail, базу данных или файловую систему, на Mock или Stub , чтобы вы могли сосредоточиться на тестировании собственного кода в изоляции внешняя подсистема. Вам не нужно проверять, что mail действительно работает.

Также см. http://www.phpunit.de/manual/3.6/en/test-doubles.html

2 голосов
/ 14 июня 2011

В чистом модульном тесте вы на самом деле не проверяете, было ли отправлено настоящее электронное письмо, а скорее вызывается ли соответствующий программный блок (в данном случае функция 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), но это может быть экземпляр объекта, который вы передадите тестируемому классу.

0 голосов
/ 14 июня 2011

Я думаю, что класс должен выполнить проверку для электронной почты, темы и другой информации, поэтому я предлагаю, чтобы это было отделено от функций.

Если у вас есть частная функция проверки, которая должна возвращать определенный результат, вы можете написать утверждение для его проверки.

эта статья может быть полезна.

Я тоже новичок в TDD, и я хочу зависеть от IDE (Netbeans), чтобы помочь мне понять этот процесс.

надеюсь, что это поможет:)

...