PHPUnit - Написание тестового класса для интерфейса и тестирование объектов с использованием фабрики - PullRequest
12 голосов
/ 23 декабря 2011

Я пишу класс, который унаследует интерфейс. Код клиента будет написан для этого интерфейса, а класс написан для его поддержки. Идея заключается в том, что позже я напишу другие классы для этого интерфейса, и объекты этих двух разных классов должны быть полностью взаимозаменяемыми. Вместо того, чтобы писать тестовый класс для этого первого класса, я хочу написать один для интерфейса.

Я планировал написать тестовый класс, который бы принимал объект конструктора для конструктора (внедрение зависимости), и использовал фабрику для создания новых экземпляров тестируемого класса.

Таким образом, если бы я хотел проверить ClassA, я мог бы передать объект ClassAFactory в конструктор тестового класса, и если бы я хотел проверить ClassB, я бы передал объект ClassBFactory. Оба класса предназначены для взаимозаменяемости, и поскольку предполагается, что тестируются только общедоступные методы, это кажется идеальным.

А как насчет тестирования конструктора? Буду ли я лучше писать абстрактный тестовый класс и реализовывать тесты конструктора в классах, которые наследуют абстрактный тестовый класс (разные классы могут создаваться по-разному)?

Если бы я использовал первую идею, я думаю, у меня был бы тестовый класс для каждого тестируемого класса, например:

class ClassATest extends [PHPUnit test case]
{
    $myFactory = new ClassAFactory();
    $myTest = new ClassTest($myFactory);

    $myTest->test1();
    $myTest->test2();
    //etc.
}

Какой лучший способ сделать это? Я хочу провести общий тест, чтобы, когда я пишу новые классы для реализации общего интерфейса, я мог просто поместить объект тех же тестов, что и для других. Но, учитывая, что разные классы будут иметь разные конструкторы, возможно, было бы лучше написать абстрактный тестовый класс и расширить его для каждого нового объекта? Что ты думаешь?

Ответы [ 2 ]

7 голосов
/ 23 декабря 2011

Я думаю, вам нужно пересмотреть свой план. Вы не можете протестировать интерфейс, и есть веская причина, почему - интерфейсы просто определяют API, а не функциональность, тестируют функциональность теста. Позвольте мне привести пример, который может помочь. Скажем, у вас есть интерфейс «обмена сообщениями». Таким образом, вы реализуете EmailMessager и SMSMessager. Теперь вам нужно протестировать их отдельно, так как с EmailMessager вам нужно убедиться, что он выполняет свои функции, может быть, проверка получателя (адрес электронной почты) и, возможно, делегирование отправки классу электронной почты и т. Д. Очевидно, что SMS-сообщение будет другим.

6 голосов
/ 24 декабря 2011

Вы можете создать абстрактный контрольный пример со всеми методами тестирования, используя свойство, которое будет устанавливаться каждым подклассом без необходимости фабрики. Он может проверить фиксированные качества, которыми должны обладать все реализации.

abstract class IAdderTestCase extends PFTC
{
    function testAdd() {
        self::assertEquals(5, $this->fixture->add(2, 3));
    }
    ...
}

class BasicAdderTest extends IAdderTestCase
{
    function setUp() {
        $this->fixture = new BasicAdder();
    }
}

PHPUnit будет вызывать setUp () перед каждым тестовым методом. Он должен вызывать все унаследованные методы тестирования для каждого конкретного подкласса плюс любые дополнительные, например, проверить конструкторы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...