PHPUnit и Git: как протестировать нечитаемый файл?

Краткая версия: для модульного тестирования мне нужен нечитаемый файл, чтобы убедиться, что выдается правильное исключение. Очевидно, что Git не может сохранить этот нечитаемый файл, поэтому я chmod 000 во время тестирования использую git update-index --assume-unchanged, чтобы Git не пытался сохранить нечитаемый файл. Но тогда я не могу проверить другую ветку, но получаю сообщение об ошибке «Ваши локальные изменения в следующих файлах будут перезаписаны при проверке».

Есть ли лучший способ протестировать ИЛИ лучший способ использовать Git, чтобы все работало хорошо?

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

public function readFile($path) {
    ...
    if(!is_readable($path))
      throw new FileNotReadableException("The file $path is not readable");
    ...
  }

Я тестирую этот метод с помощью PHPUnit, и один тест, в частности, должен (косвенно) вызывать исключение FileNotReadableException:

/**
 * @expectedException Data\Exceptions\FileNotReadableException
 */
public function testFileNotReadableException() {
  $file = '/_files/6504/58/6332_unreadable.xlsx';
  @chmod(__DIR__ . $file, 0000);
  $import = Import::find(58);
  $import->importFile(array('ID'=>2, 'newFilename'=> $file), __DIR__);
}

После теста git checkout other_branch прервется:

error: Your local changes to the following files would be overwritten by checkout:
    Data/Tests/_files/6504/58/6332_unreadable.xlsx
Please, commit your changes or stash them before you can switch branches.
Aborting

person jchamberlain    schedule 19.11.2013    source источник


Ответы (1)


У вас есть несколько вариантов.

Добавьте в тест метод tearDown(), который сбрасывает права доступа к файлу, чтобы git не думал, что файл был изменен. Затем, даже если тест не пройден, файл будет сброшен.

http://phpunit.de/manual/current/en/fixtures.html

public function tearDown() {
     @chmod(__DIR__ . $file, 0755); //Whatever the old permissions were;
}

Если вы используете PHP 5.3+, вы можете использовать интервалы имен и имитировать функцию is_readable. В тестовом файле переопределите is_readable своей собственной функцией. Вам нужно будет убедиться, что ваше переопределение находится в том же пространстве имен, что и ваш класс, который вы тестируете.

http://www.schmengler-se.de/-php-mocking-built-in-functions-like-time-in-unit-tests

В своем классе вы бы сделали это:

namespace SUT

class SUT {
    public function readFile($path) {
        ...
        if(!is_readable($path))
          throw new FileNotReadableException("The file $path is not readable");
        ...
  }
}

Затем в своем тесте вы делаете следующее:

namespace SUT

function is_readable($filename) {
    if (str_pos('unreadable') !== FALSE)) {
        return false;
    }

    return true;
}

class SUTTest extends PHPUNIT_Framework_TestCase {
    /**
     * @expectedException Data\Exceptions\FileNotReadableException
     */
     public function testFileNotReadableException() {
        $file = '/_files/6504/58/6332_unreadable.xlsx';
        $sut = new SUT();
        $sut->readFile($file);
     }
}

Тогда вам даже не придется включать файлы в репозиторий или беспокоиться о разрешениях на него.

person Schleis    schedule 19.11.2013
comment
Хороший! Насмешка is_readable() действительно элегантна и никогда не приходила мне в голову. (Хотя публики там быть не должно.) - person jchamberlain; 20.11.2013
comment
Поскольку мои тесты находятся в другом пространстве имен (Data\Tests), я создал отдельный файл functions_override.php, который использует пространство имен Data. Я включаю это в тест, и он отлично работает. Спасибо! - person jchamberlain; 20.11.2013