Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHPUnit & Git: How to test with unreadable file?

Short version: For unit testing, I need an unreadable file to make sure the correct exception is thrown. Obviously, that unreadable file can't be stored by Git, so I chmod 000 at testing time and use git update-index --assume-unchanged so that Git doesn't try storing the unreadable file. But then I can't checkout a different branch, but get the error "Your local changes to the following files would be overwritten by checkout."

Is there a better way to test, OR a better way to use Git so that everything plays nicely?

Long version: In one class, I have a method to read a file so that its contents can be imported into a database:

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

I test that method using PHPUnit, and one test in particular should (indirectly) trigger the 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__);
}

After a test, git checkout other_branch will abort:

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
like image 328
jchamberlain Avatar asked Nov 19 '13 19:11

jchamberlain


People also ask

What is PHPUnit used for?

PHPUnit is a programmer-oriented testing framework for PHP. It is an instance of the xUnit architecture for unit testing frameworks. PHPUnit 9 is the current stable version. PHPUnit 10 is currently in development.

What are PHPUnit fixtures?

One of the most time-consuming parts of writing tests is writing the code to set the world up in a known state and then return it to its original state when the test is complete. This known state is called the fixture of the test.

How do I run a single PHPUnit test?

How to Run Tests in PHPUnit. You can run all the tests in a directory using the PHPUnit binary installed in your vendor folder. You can also run a single test by providing the path to the test file. You use the --verbose flag to get more information on the test status.


1 Answers

You have a couple of options.

Add a tearDown() method to the test that resets the file permissions so that git does not think that the file was modified. Then even if the test fails the file will be reset.

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

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

If you are using PHP 5.3+, you can use name-spacing and mock the is_readable function. In your test file, override is_readable with your own function. You will need to make sure that your override is in the same namespace as your class that you are testing.

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

In your class you would do this:

namespace SUT

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

Then in your test you do the following:

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);
     }
}

You would then not even have to include the files in your repo or worry about the permissions on it.

like image 125
Schleis Avatar answered Sep 30 '22 16:09

Schleis