[phpunit] Inline Teardown

Baranov_Dron

Новичок
[phpunit] Inline Teardown

Часто бывает, такое, что каждый тест в наборе тестов, создаёт и работает со своим файлом, и вешать очистку файлов, их удаление, наоборот создание и т.д. не охото на функцию tearDown(). Так как там будет куча конструкций вида:
PHP:
public function tearDown()
{
@unlink($this->getTempDir() . 'test_create.xml';
@unlink($this->getTempDir() . 'test_create.txt';
@unlink($this->getTempDir() . 'test_create.doc';

@touch($this->getTempDir() . 'test_delete.xml';
@touch($this->getTempDir() . 'test_delete.txt';
@touch($this->getTempDir() . 'test_delete.doc';
}
которые в свою очередь очень сильно ухудшают чтение тестов и использование их как документации.

Для моей задачи весьма подошёл паттерн Inline Teardown .
Там дан весьма красивый пример кода:
PHP:
   public void testGetFlightsByOriginAirport_NoFlights_TDGC() throws Exception {
      // Fixture setup
      BigDecimal outboundAirport = createTestAirport("1OF");
      try {
         // Exercise System
         List flightsAtDestination1 = facade.getFlightsByOriginAirport(outboundAirport);
         // Verify Outcome
         assertEquals(0,flightsAtDestination1.size());
      } finally {
         if (outboundAirport!=null) {
            facade.removeAirport(outboundAirport);
         }
      }
   }
.
Код очистки
PHP:
if (outboundAirport!=null) {
    facade.removeAirport(outboundAirport);
}
Работает всегда!

Попробовал пустить два теста, наспешь написанных.
PHP:
<?php
class prostoTest extends PHPUnit_Framework_TestCase
{
    public function testOne()
    {
        try
        {
            $this->assertEquals(1, 2);
        }
        catch (Exception $e) {}

        echo 'cleaned_one';
    }

    public function testTwo()
    {
        $this->assertEquals(1, 2);

        echo 'cleaned_two';
    }
}
?>
Результат:
C:\xampp\htdocs\phpunit>phpunit prostoTest
PHPUnit 3.3.9 by Sebastian Bergmann.

cleaned_one.F

Time: 0 seconds

There was 1 failure:

1) testTwo(prostoTest)
Failed asserting that <integer:2> matches expected value <integer:1>.
C:\xampp\htdocs\phpunit\prostoTest.php:17

FAILURES!
Tests: 2, Assertions: 2, Failures: 1.
Как можно заметить - в первом тесте $this->assertEquals(1, 2); определилось как успешное сравнение!
А во втором тесте не сработала очистка. Моя же цель, чтобы сработала очистка и чтобы показывалось, что да, отловлена ошибка в тестируемой системе и данные этой ошибки(во втором тесте это Failed asserting that <integer:2> matches expected value <integer:1>).

Как собственно это реализовать? Ведь конструкции try {} finally {} в php нет.

-~{}~ 07.03.09 19:01:

up(
 

korchasa

LIMB infected
Мы обычно в этом случае не паримся и делаем очистку общей. Т.е. я бы создавал эти файлы не в $this->getTempDir(), а в $this->getTempDir().'/test_files/'. Ну а в tearDown просто unset($this->getTempDir().'/test_files/').
 

Baranov_Dron

Новичок
Автор оригинала: korchasa
Т.е. я бы создавал эти файлы не в $this->getTempDir(), а в $this->getTempDir().'/test_files/'.
Ну а в tearDown просто unset($this->getTempDir().'/test_files/').
korchasa я долго думал над этой фразой, но так и не понял о чём она, и код unset($this->getTempDir().'/test_files/') вообще ввёл в ступор.

По поводу общей очистки это понятно всё, я её сейчас и использую:
PHP:
class StArticleTest extends PHPUnit_Framework_TestCase
{
    public function tearDown()
    {
        //очистка для теста testSaveSuccessThenCategoryNotFound()
        @unlink($this->getDir(). 'categorynotfound'. DIRECTORY_SEPARATOR . 'test.txt');
        @rmdir($this->getDir(). 'categorynotfound');
    }

    /**
     * Тестируем сохранение статьи, в случае, когда категории не существует.
     *
     * @return void
     */
    public function testSaveSuccessThenCategoryNotFound()
    {
        $article = new StArticle($this->getDir(), 'categorynotfound', 'test');
        $article->setContent('test');

        $this->assertTrue($article->save());
        $this->assertEquals('test', file_get_contents($this->getDir(). 'categorynotfound' .
          DIRECTORY_SEPARATOR . 'test.txt'));
    }

    /**
     * Вспомогательная функция для получения пути к директории _files.
     *
     * @return void
     */
    private function getDir()
    {
        return dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' .
          DIRECTORY_SEPARATOR;
    }
}
?>
Но это получается весьма неудобно, и тест становится тяжелее читать. Конструкция try{} finally{} куда красивше выглядит.
А подобных конструкций в php нет?
 

korchasa

LIMB infected
Автор оригинала: Baranov_Dron
korchasa я долго думал над этой фразой, но так и не понял о чём она, и код unset($this->getTempDir().'/test_files/') вообще ввёл в ступор.
Нда, чего только под вином не напишешь :) Вместо unset следует читать rmdir
PHP:
class StArticleTest extends PHPUnit_Framework_TestCase
{
    public function setUp()
    {
        mkdir($this->getDir());
    }

    public function tearDown()
    {
        @rmdir($this->getDir());
    }

    public function testSaveSuccessThenCategoryNotFound()
    {
        $article = new StArticle($this->getDir(), 'categorynotfound', 'test');
        $article->setContent('test');

        $this->assertTrue($article->save());
        $this->assertEquals('test', file_get_contents($this->getDir(). 'categorynotfound' .
          DIRECTORY_SEPARATOR . 'test.txt'));
    }

    private function getDir()
    {
        return dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' .
          DIRECTORY_SEPARATOR;
    }
}
?>
 

Baranov_Dron

Новичок
<Нда, чего только под вином не напишешь Вместо unset следует читать rmdir
аа мысленно я думал о том, что ты имел в виду unlink))

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

whirlwind

TDD infected, paranoid
PHP:
class DC_prostoTest extends PHPUnit_Framework_TestCase
{
    public function testOne()
    {
        try
        {
            $this->assertEquals(1, 2);
        }
        catch (Exception $e) {
            
        }

        echo 'cleaned_one';
        if ( $e ) throw $e;
    }

    public function testTwo()
    {
        $this->assertEquals(1, 2);

        echo 'cleaned_two';
    }
}
Код:
cleaned_oneFF

Time: 0 seconds

There were 2 failures:

1) testOne(DC_prostoTest)
Failed asserting that <integer:2> matches expected value <integer:1>.
/home/whirlwind/work/DC/tests/DC/test.php:15

2) testTwo(DC_prostoTest)
Failed asserting that <integer:2> matches expected value <integer:1>.
/home/whirlwind/work/DC/tests/DC/test.php:27

FAILURES!
Tests: 2, Assertions: 2, Failures: 2.
 
Сверху