Тестовый объект с функциями файловой системы - PullRequest
3 голосов
/ 09 декабря 2010

Я пишу некоторые объекты, которые широко используют файловую систему. Я не уверен, как правильно их проверить.

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

Единственный способ, с помощью которого я могу думать о тестировании, - это работать с файловой системой. Проблема в том, что тесты будут запускаться как в браузере, так и в командной строке, поэтому мне нужно работать в каталоге с доступом для записи для всех. Более того, это не кажется очень портативным решением.

Есть идеи?

Ответы [ 4 ]

5 голосов
/ 09 декабря 2010

Вы можете смоделировать файловую систему с помощью vfsStream , как , предложенное в Руководстве по PHPUnit :

vfsStream - это потоковая оболочка для виртуальной файловой системы, которая можетбыть полезным в модульных тестах для проверки реальной файловой системы […] Если в вашей системе доступен установщик PEAR, вам нужно только выполнить следующие команды:

$ pear channel-discover pear.bovigo.org
$ pear install bovigo/vfsStream-beta

Существует примеры на Github , а также Wiki

1 голос
/ 17 апреля 2013

Другим вариантом является макетирование функций PHP, использующих файловую систему, с помощью runkit .Не уверен, что это лучшее решение, но оно работает.Существует phpunit-mockfunction - расширение PHPUnit, которое упрощает фиктивные функции PHP.

Так, например:

class Tests extends PHPUnit_Framework_TestCase {
    // ... setUp, tearDown, other tests...

    function test_1(){
        $file_size_to_return = 10;

        $fake_filesize = new PHPUnit_Extensions_MockFunction('filesize', $this->obj->tested_method);
        $fake_filesize->expects($this->once())->will($this->returnValue($file_size_to_return));

        $this->obj->tested_method(); // actually run method we want test that contains filesize() function...
    }
}
1 голос
/ 10 декабря 2010

На мой взгляд, у вас есть три варианта:

  • Примите, что некоторые тесты лучше использовать как интеграционные тесты.Запустите тест, создав небольшой мир для запуска теста (в% TEMP%, на основе имени класса / метода), а затем уничтожьте его, когда закончите.
  • Изучите свой уровень абстракции и извлекитефайл IO из класса.Создать интерфейс для этого.Остальные используют интеграционные тесты (но это будет очень мало).Это отличается от приведенного выше тем, что вместо того, чтобы делать файл. Читайте намерение, скажем, ioThingie.loadSettings ().
  • Макет ввода-вывода (как предложено Гордон выше).

Обычно я использую сочетание опций один и два и использую только три для крайних случаев, как я нахожу в C #, когда имитация необработанного слоя ввода-вывода (System.IO.File) действительно только показывает, что вы можете писать операторы насмешки,и делает ваш тест немного слишком зависимым от реализации, однако приведенные выше vfs выглядят так, будто они имитируют FS, а не объекты.

1 голос
/ 09 декабря 2010

Представьте php-функции очень низкого уровня, которые не делают ничего, кроме вызова функций файловой системы, и используйте их в своем коде.

Затем в вашем тестовом жгуте переопределите эти функции с заглушками (которые, возможно, записывают, что они были вызваны). Таким образом, вы можете убедиться, что ваш код будет вызывать в действующей системе правильные функции PHP низкого уровня. Для модульного теста это все, что вы можете сделать, на самом деле.

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