Функциональные тесты: загрузка файла (attachFile)

Всё про тестирование в Yii 2.0
Евгений Емельянов
Сообщения: 167
Зарегистрирован: 2015.06.10, 10:43

Функциональные тесты: загрузка файла (attachFile)

Сообщение Евгений Емельянов »

В функциональном тесте (ФТ) не проходит загрузка файла. (Через браузер и в приемочном все работает).
Временный файл создается, но не перемещается в постоянное хранилище (папка для файла создается). Как запустить этот тест с сохранением файла? Ниже результаты дебаггинга.
Это код в FunctionalCest

Код: Выделить всё

...
$I->attachFile('input[type="file"]', 'pic02.jpg');
$I->click('submit');
...
Удалось установить, что временный загруженный файл не распознается функцией move_uploaded_file() как загруженный:
\yii2\web\UploadedFile:

Код: Выделить всё

public function saveAs($file, $deleteTempFile = true)
    {
        if ($this->error == UPLOAD_ERR_OK) {
            if ($deleteTempFile) {
                return move_uploaded_file($this->tempName, $file); // ЗДЕСЬ false!
                          // tempName - 'd:\\openserver\\userdata\\temp/36f4dd9b007eaae0755d1e9713cfc55cd92d2519.jpg'
            } elseif (is_uploaded_file($this->tempName)) { // в $_FILES[model][tmp_name][image] - 
                          // - 'd:\\openserver\\userdata\\temp/36f4dd9b007eaae0755d1e9713cfc55cd92d2519.jpg' 
                return copy($this->tempName, $file);
            }
        }
        return false;
    } 
Вот содержимое Uploaded из ФТ:

Код: Выделить всё

yii\web\UploadedFile#1
(
    [name] => '573c32ca2604c.jpg'
    [tempName] => 'd:\\openserver\\userdata\\temp/36f4dd9b007eaae0755d1e9713cfc55cd92d2519.jpg'
    [type] => ''
    [size] => '12961'
    [error] => '0'
) 
Вот при обычной загрузке в браузере:

Код: Выделить всё

yii\web\UploadedFile#1
(
    [name] => '573c3473e488d.jpg'
    [tempName] => 'W:\\userdata\\temp\\php2E7A.tmp'
    [type] => 'image/jpeg'
    [size] => 12961
    [error] => 0
) 
Возможно, проблема в формировании пути к временному файлу в ФТ, пробовал путь задавать в файле теста, не помогло:

Код: Выделить всё

ini_set('upload_tmp_dir', 'w:/userdata/temp/'); 
Может, кто сталкивался с такой проблемой и решил ее? Поделитесь решением.
------
Используется: OpenServer, PHP 5.6.19, тест - FunctionalCest, https://github.com/mohorev/yii2-upload-behavior
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение zelenin »

Для правильной работы, функции is_uploaded_file() нужен аргумент вида $_FILES['userfile']['tmp_name'], - имя закачиваемого файла на клиентской машине $_FILES['userfile']['name'] не подходит.
у вас видимо $_FILES не заполняется.
Евгений Емельянов
Сообщения: 167
Зарегистрирован: 2015.06.10, 10:43

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение Евгений Емельянов »

zelenin писал(а):
Для правильной работы, функции is_uploaded_file() нужен аргумент вида $_FILES['userfile']['tmp_name'], - имя закачиваемого файла на клиентской машине $_FILES['userfile']['name'] не подходит.
у вас видимо $_FILES не заполняется.
Заполняется, только иначе чем при обычном способе (через браузер) - различия приводил уже:

Код: Выделить всё

yii\web\UploadedFile#1 // это $_FILES из ФТ
(
    [name] => '573c32ca2604c.jpg'
    [tempName] => 'd:\\openserver\\userdata\\temp/36f4dd9b007eaae0755d1e9713cfc55cd92d2519.jpg' // имя файла формируется иначе
    [type] => '' // тип не передается
    [size] => '12961'
    [error] => '0'
)  
а это при обычной отправке:

Код: Выделить всё

yii\web\UploadedFile#1
(
    [name] => '573c3473e488d.jpg'
    [tempName] => 'W:\\userdata\\temp\\php2E7A.tmp'
    [type] => 'image/jpeg'
    [size] => 12961
    [error] => 0
)  
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение zelenin »

вы показываете UploadedFile, я пишу про $_FILES.
Евгений Емельянов
Сообщения: 167
Зарегистрирован: 2015.06.10, 10:43

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение Евгений Емельянов »

zelenin писал(а):вы показываете UploadedFile, я пишу про $_FILES.
Вставляю сюда копированием - они аналогичны (по данным)
Последний раз редактировалось Евгений Емельянов 2016.05.18, 15:12, всего редактировалось 1 раз.
Евгений Емельянов
Сообщения: 167
Зарегистрирован: 2015.06.10, 10:43

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение Евгений Емельянов »

Вот из консоли:

Код: Выделить всё

try to test (modules\pages\PagesCrudCest::tryToTest)... yii\web\UploadedFile#1
(
    [name] => '573c5babd3430.jpg'
    [tempName] => 'd:\\openserver\\userdata\\temp/c536462e2f6e78d4add5f9a5d5a1acd1ba9c25d9.jpg'
    [type] => ''
    [size] => '12961'
    [error] => '0'
)
// это $_FILES:
[
    'Pages' => [
        'name' => [
            'image' => 'pic02.jpg'
        ]
        'type' => [
            'image' => ''
        ]
        'tmp_name' => [
            'image' => 'd:\\openserver\\userdata\\temp/c536462e2f6e78d4add5f9a5d5a1acd1ba9c25d9.jpg'
        ]
        'error' => [
            'image' => '0'
        ]
        'size' => [
            'image' => '12961'
        ]
    ]
]
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение zelenin »

Евгений Емельянов писал(а):
zelenin писал(а):вы показываете UploadedFile, я пишу про $_FILES.
Вставляю сюда копированием - они аналогичны (по данным)
вот и скопируйте оба вар дампа, чтобы вопросов не было.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение zelenin »

Евгений Емельянов писал(а):Вот из консоли:

Код: Выделить всё

try to test (modules\pages\PagesCrudCest::tryToTest)... yii\web\UploadedFile#1
(
    [name] => '573c5babd3430.jpg'
    [tempName] => 'd:\\openserver\\userdata\\temp/c536462e2f6e78d4add5f9a5d5a1acd1ba9c25d9.jpg'
    [type] => ''
    [size] => '12961'
    [error] => '0'
)
// это $_FILES:
[
    'Pages' => [
        'name' => [
            'image' => 'pic02.jpg'
        ]
        'type' => [
            'image' => ''
        ]
        'tmp_name' => [
            'image' => 'd:\\openserver\\userdata\\temp/c536462e2f6e78d4add5f9a5d5a1acd1ba9c25d9.jpg'
        ]
        'error' => [
            'image' => '0'
        ]
        'size' => [
            'image' => '12961'
        ]
    ]
] 
ага, теперь еще раз читаем:
Для правильной работы, функции is_uploaded_file() нужен аргумент вида $_FILES['userfile']['tmp_name'], - имя закачиваемого файла на клиентской машине $_FILES['userfile']['name'] не подходит.
Евгений Емельянов
Сообщения: 167
Зарегистрирован: 2015.06.10, 10:43

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение Евгений Емельянов »

zelenin писал(а):
Евгений Емельянов писал(а):
zelenin писал(а):вы показываете UploadedFile, я пишу про $_FILES.
Вставляю сюда копированием - они аналогичны (по данным)
вот и скопируйте оба вар дампа, чтобы вопросов не было.
Ну так ужЕ...
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение zelenin »

Евгений Емельянов писал(а):Т.е. Pages - лишний элемент?
т.е. у вас в tempName вложенный массив.. в общем копайте в этом направлении. файл помечается незагруженным через POST из-за несоответствия в FILES. Гугл в помощь https://www.google.ru/search?client=ubu ... fFZI-OgbAH
Евгений Емельянов
Сообщения: 167
Зарегистрирован: 2015.06.10, 10:43

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение Евгений Емельянов »

Тестирование только начинаю осваивать и, к сожалению, не знаю других способов закачать файл в тестах. Как это можно правильно сделать?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение zelenin »

Евгений Емельянов писал(а):Тестирование только начинаю осваивать и, к сожалению, не знаю других способов закачать файл в тестах. Как это можно правильно сделать?
@Тестировщики, ау!)
Евгений Емельянов
Сообщения: 167
Зарегистрирован: 2015.06.10, 10:43

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение Евгений Емельянов »

zelenin писал(а):
Евгений Емельянов писал(а):Т.е. Pages - лишний элемент?
т.е. у вас в tempName вложенный массив.. в общем копайте в этом направлении. файл помечается незагруженным через POST из-за несоответствия в FILES. Гугл в помощь https://www.google.ru/search?client=ubu ... fFZI-OgbAH
Наверное, надо пояснить про "в tempName вложенный массив". Т.к. в дампе при загрузке в браузере структура массива такая же:

Код: Выделить всё

yii\web\UploadedFile#1
(
    [name] => '573c61c4e9cb2.jpg'
    [tempName] => 'W:\\userdata\\temp\\php3301.tmp'
    [type] => 'image/jpeg'
    [size] => 26525
    [error] => 0
)[
    'Pages' => [
        'name' => [
            'image' => 'pic03.jpg'
        ]
        'type' => [
            'image' => 'image/jpeg'
        ]
       'tmp_name' => [
            'image' => 'W:\\userdata\\temp\\php3301.tmp' // здесь тоже вложенный массив
        ]
        'error' => [
            'image' => 0
        ]
        'size' => [
            'image' => 26525
        ]
    ]
]
И при этом файл нормально загружается.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение zelenin »

отлично. продолжайте в гугле - ссылок куча, обязательно найдете ответ.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение ElisDN »

Евгений Емельянов писал(а):Удалось установить, что временный загруженный файл не распознается функцией move_uploaded_file() как загруженный
Да, не перемещается из-за этого. Попробуйте подменить функции в тестах в functional/_bootstrap.php:

Код: Выделить всё

namespace yii\web {
    function move_uploaded_file($from, $to) {
        rename($from, $to);
    }
    function is_uploaded_file($file) {
        return true;
    }
}
Евгений Емельянов
Сообщения: 167
Зарегистрирован: 2015.06.10, 10:43

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение Евгений Емельянов »

ElisDN писал(а):Попробуйте подменить функции в тестах в functional/_bootstrap.php
Дмитрий, Большой Вам респект! Спасибо за решение. Единственно, хотелось бы понять принцип, почему так происходит, а то с тестами одно шаманство!
Для тех, кто столкнется с подобной проблемой выкладываю код functional/_bootstrap.php:

Код: Выделить всё

namespace yii\web {

    function move_uploaded_file($tempFile, $destination)
    {
        return copy($tempFile, $destination);
    }
}

namespace {

    ini_set('xdebug.max_nesting_level', 1000);

    defined('YII_DEBUG') or define('YII_DEBUG', true);
    defined('YII_ENV') or define('YII_ENV', 'test');

    defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', dirname(dirname(dirname(__DIR__))));

    defined('YII_BACKEND_TEST_ENTRY_URL') or define('YII_BACKEND_TEST_ENTRY_URL', parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_PATH));
    defined('YII_TEST_BACKEND_ENTRY_FILE') or define('YII_TEST_BACKEND_ENTRY_FILE', YII_APP_BASE_PATH . '/backend/web/index-test.php');

    require_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
    require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
    require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
    require_once(YII_APP_BASE_PATH . '/backend/config/bootstrap.php');

// set correct script paths

// the entry script file path for functional and acceptance tests
    $_SERVER['SCRIPT_FILENAME'] = YII_TEST_BACKEND_ENTRY_FILE;
    $_SERVER['SCRIPT_NAME']     = YII_BACKEND_TEST_ENTRY_URL;
    $_SERVER['SERVER_NAME']     = parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_HOST);
    $_SERVER['SERVER_PORT']     = parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_PORT) ? : '80';

    Yii::setAlias('@tests', dirname(dirname(__DIR__)));

    \Codeception\Util\Autoload::registerSuffix('Page', __DIR__ . DIRECTORY_SEPARATOR . '_pages');
}
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение ElisDN »

Евгений Емельянов писал(а):Единственно, хотелось бы понять принцип, почему так происходит, а то с тестами одно шаманство!
Функции сначала ищутся в текущем пространстве имён, а потом уже в глобальном (если не задано сразу со слешем \move_uploaded_file). Просто помещаем замену в то же пространство имён, в котором находится yii\web\UploadedFile, и он уже находит yii\web\move_uploaded_file.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение zelenin »

ElisDN писал(а):
Евгений Емельянов писал(а):Единственно, хотелось бы понять принцип, почему так происходит, а то с тестами одно шаманство!
Функции сначала ищутся в текущем пространстве имён, а потом уже в глобальном (если не задано сразу со слешем \move_uploaded_file). Просто помещаем замену в то же пространство имён, в котором находится yii\web\UploadedFile, и он уже находит yii\web\move_uploaded_file.
он имел в виду почему move_uploaded_file не работает
Евгений Емельянов
Сообщения: 167
Зарегистрирован: 2015.06.10, 10:43

Re: Функциональные тесты: загрузка файла (attachFile)

Сообщение Евгений Емельянов »

И еще была проблема - убил день пока решил, - может кому-то пригодится. Выполнял в ФТ загрузку файла

Код: Выделить всё

$I->amOnPage('/backend/web/index-test.php/pages/default/create');
        $I->seeInTitle('Новая страница');
        $I->amGoingTo('submit empty form');
        $I->click('Создать');
        $I->expectTo('see validation errors');
        $I->see('Необходимо заполнить «Название».'); // ошибки валидации не дадут оправить файл
        $I->see('Необходимо заполнить «Заголовок».');
        ...
        
        $I->amGoingTo('create new page with correct data');
        $I->fillField('Название', 'Минеральное царство');
        $I->fillField('Заголовок', 'Минеральное царство');
        $I->attachFile('input[type="file"]', 'pic02.jpg'); // загрузить файл
        ...
        $I->click('Создать');
        $I->dontSee('Необходимо заполнить');
        $I->expectTo('see new record');
В приемочном тесте это работает, тест проходит, в ФТ не проходит. Файл вообще не попадает в $_FILES! Оказалось, такая ситуация только после не пройденной валидации в той же форме. Если поменять местами последовательность проверок, то тест проходит.
Ответить